home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Term / Extras / Source / term-source.lha / TextBufferWindow.c < prev    next >
C/C++ Source or Header  |  1996-10-20  |  69KB  |  2,933 lines

  1. /*
  2. **    TextBufferWindow.c
  3. **
  4. **    Support routines for the text buffer window and screen.
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16. /****************************************************************************/
  17.  
  18. STATIC VOID Buffer_AskPosition(struct MarkerContext *Context, LONG *Column, LONG *Line, WORD Mode);
  19. STATIC VOID Buffer_Scroll(struct MarkerContext *Context, LONG DeltaX, LONG DeltaY);
  20. STATIC VOID Buffer_Highlight(struct MarkerContext *Context, LONG Line, LONG Left, LONG Right);
  21. STATIC BOOL Buffer_Put(APTR UserData, STRPTR Buffer, LONG Length);
  22. STATIC BOOL Buffer_PutLine(APTR UserData, STRPTR Buffer, LONG Length);
  23. STATIC BOOL Buffer_Transfer(struct MarkerContext *Context, LONG Line, LONG Left, LONG Right, MARKER_Put Put, APTR UserData);
  24. STATIC BOOL Buffer_PickWord(struct MarkerContext *Context, LONG Left, LONG Top, LONG *WordLeft, LONG *WordRight);
  25. STATIC APTR Buffer_TransferStartStop(struct MarkerContext *Context, APTR UserData, ULONG Qualifier);
  26. STATIC VOID BufferMarkerStop(TextBufferInfo *BufferInfo);
  27. STATIC VOID BufferMarkWord(TextBufferInfo *BufferInfo);
  28. STATIC VOID BufferMarkerStart(TextBufferInfo *BufferInfo, UWORD MsgQualifier);
  29. STATIC VOID BufferMarkerInterrupt(TextBufferInfo *BufferInfo);
  30. STATIC VOID BufferMarkerMoveMouse(TextBufferInfo *BufferInfo);
  31. STATIC VOID BufferMarkerTransfer(TextBufferInfo *BufferInfo, UWORD MsgQualifier);
  32. STATIC VOID FlushMsg(struct Window *Window);
  33. STATIC VOID BufferClear(TextBufferInfo *BufferInfo, LONG Left, LONG Top, LONG Right, LONG Bottom);
  34. STATIC VOID BufferScroll(TextBufferInfo *BufferInfo, LONG Lines);
  35. STATIC VOID BufferComplement(TextBufferInfo *BufferInfo, LONG SrcX, LONG SrcY, LONG Width, LONG Height);
  36. STATIC VOID DeleteScroller(TextBufferInfo *BufferInfo);
  37. STATIC BOOL CreateScroller(TextBufferInfo *BufferInfo, LONG Height);
  38. STATIC VOID PrintLine(TextBufferInfo *BufferInfo, STRPTR Buffer, LONG LineNumber);
  39. STATIC VOID PrintLineWithMarker(TextBufferInfo *BufferInfo, STRPTR Buffer, LONG LineNumber, LONG AbsoluteLine);
  40. STATIC LONG RedrawScreen(TextBufferInfo *BufferInfo, LONG FirstLine);
  41. STATIC VOID BufferDestructor(struct DataMsg *Item);
  42. STATIC VOID BufferSerWrite(TextBufferInfo *BufferInfo, APTR Data, LONG Size);
  43. STATIC VOID StartSearch(TextBufferInfo *BufferInfo, struct SearchInfo *SearchInfo, STRPTR SearchBuffer);
  44. STATIC BOOL HandleBuffer(struct SignalSemaphore *Access, TextBufferInfo **Data);
  45. STATIC VOID DeleteBufferInfo(TextBufferInfo *BufferInfo);
  46. STATIC TextBufferInfo *CreateBufferInfo(struct Screen *Parent, BOOL *pSearchForward, BOOL *pIgnoreCase, BOOL *pWholeWords, LONG *pTopLine);
  47. STATIC VOID SAVE_DS BufferServer(VOID);
  48. STATIC VOID SAVE_DS ReviewServer(VOID);
  49.  
  50. /****************************************************************************/
  51.  
  52.     /* Gadget ID codes. */
  53.  
  54. enum    {    GAD_SCROLLER,
  55.             GAD_UP,
  56.             GAD_DOWN
  57.         };
  58.  
  59.     /* Menu ID codes. */
  60.  
  61. enum    {    MEN_SEARCH,
  62.             MEN_REPEAT,
  63.             MEN_GOTO,
  64.             MEN_CLEARBUF_CONTENTS,
  65.             MEN_QUITBUF,
  66.             MEN_COPYCLIP,
  67.             MEN_PASTECLIP,
  68.             MEN_CLEARCLIP,
  69.             MEN_SELECT_ALL_CLIP
  70.         };
  71.  
  72. /****************************************************************************/
  73.  
  74. STATIC VOID
  75. Buffer_AskPosition(struct MarkerContext *Context,LONG *Column,LONG *Line,WORD Mode)
  76. {
  77.     TextBufferInfo *BufferInfo;
  78.     struct TextExtent Extent;
  79.     LONG Left,Top;
  80.  
  81.     BufferInfo = Context->UserData;
  82.  
  83.     Left    = BufferInfo->Window->MouseX - BufferInfo->Left;
  84.     Top        = BufferInfo->Window->MouseY - BufferInfo->Top;
  85.  
  86.     SafeObtainSemaphoreShared(&BufferSemaphore);
  87.  
  88.     if(Mode == MARKERASK_Scroll)
  89.     {
  90.         if(Top < 0)
  91.         {
  92.             *Column    = 0;
  93.             *Line    = -1;
  94.         }
  95.         else if(Top >= BufferInfo->Height)
  96.         {
  97.             *Column    = Context->NumVisibleColumns - 1;
  98.             *Line    = Context->NumVisibleLines;
  99.         }
  100.         else
  101.         {
  102.             LONG ThisLine;
  103.  
  104.             ThisLine = Top / BufferInfo->LocalTextFontHeight;
  105.  
  106.             if(BufferInfo->TopLine + ThisLine >= Lines)
  107.             {
  108.                 *Column    = Context->NumVisibleColumns - 1;
  109.                 *Line    = Context->NumVisibleLines;
  110.             }
  111.             else
  112.             {
  113.                 if(Left < 0)
  114.                     *Column = -1;
  115.                 else if (Left >= BufferInfo->Width)
  116.                     *Column = Context->NumVisibleColumns;
  117.                 else
  118.                 {
  119.                     STRPTR TheLine = BufferLines[BufferInfo->TopLine + ThisLine];
  120.  
  121.                     if(TheLine[-1])
  122.                         *Column = TextFit(BufferInfo->RPort,TheLine,TheLine[-1],&Extent,NULL,1,Left,32767);
  123.                     else
  124.                         *Column = 0;
  125.                 }
  126.  
  127.                 *Line = ThisLine;
  128.             }
  129.         }
  130.     }
  131.     else
  132.     {
  133.         LONG ThisLine;
  134.  
  135.         if(Top < 0)
  136.             Top = 0;
  137.         else if(Top >= BufferInfo->Height)
  138.             Top = BufferInfo->Height - 1;
  139.  
  140.         if(Left < 0)
  141.             Left = 0;
  142.         else if (Left >= BufferInfo->Width)
  143.             Left = BufferInfo->Width - 1;
  144.  
  145.         ThisLine = Top / BufferInfo->LocalTextFontHeight;
  146.  
  147.         if(BufferInfo->TopLine + ThisLine >= Lines)
  148.         {
  149.             STRPTR TheLine;
  150.  
  151.             ThisLine = Lines - BufferInfo->TopLine - 1;
  152.  
  153.             TheLine = BufferLines[BufferInfo->TopLine + ThisLine];
  154.  
  155.             if(TheLine[-1] > 0)
  156.                 *Column = TextFit(BufferInfo->RPort,TheLine,TheLine[-1],&Extent,NULL,1,Left,32767);
  157.             else
  158.                 *Column = 0;
  159.  
  160.             *Line = ThisLine;
  161.         }
  162.         else
  163.         {
  164.             if(Left < 0)
  165.                 *Column = 0;
  166.             else
  167.             {
  168.                 STRPTR TheLine;
  169.  
  170.                 TheLine = BufferLines[BufferInfo->TopLine + ThisLine];
  171.  
  172.                 if(TheLine[-1] > 0)
  173.                     *Column = TextFit(BufferInfo->RPort,TheLine,TheLine[-1],&Extent,NULL,1,Left,32767);
  174.                 else
  175.                     *Column = 0;
  176.             }
  177.  
  178.             *Line = ThisLine;
  179.         }
  180.     }
  181.  
  182.     ReleaseSemaphore(&BufferSemaphore);
  183. }
  184.  
  185.     /* Scroll the visible region. */
  186.  
  187. STATIC VOID
  188. Buffer_Scroll(struct MarkerContext *Context,LONG UnusedDeltaX,LONG DeltaY)
  189. {
  190.     TextBufferInfo *BufferInfo;
  191.     LONG NewTopLine;
  192.  
  193.     BufferInfo = Context->UserData;
  194.  
  195.     NewTopLine = BufferInfo->TopLine + DeltaY;
  196.  
  197.     if(NewTopLine < 0)
  198.         NewTopLine = 0;
  199.     else if (NewTopLine + BufferInfo->NumBufferLines >= Lines)
  200.         NewTopLine = Lines - BufferInfo->NumBufferLines;
  201.  
  202.     if(NewTopLine >= 0 && NewTopLine != BufferInfo->TopLine)
  203.     {
  204.         BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,NewTopLine);
  205.  
  206.         BufferInfo->TopLine = NewTopLine;
  207.  
  208.         SetGadgetAttrs((struct Gadget *)BufferInfo->Scroller,BufferInfo->Window,NULL,
  209.             PGA_Top,BufferInfo->TopLine,
  210.         TAG_DONE);
  211.     }
  212. }
  213.  
  214.     /* Highlight a line of text between the "Left" and "Right" column (inclusive).
  215.      */
  216.  
  217. STATIC VOID
  218. Buffer_Highlight(struct MarkerContext *Context,LONG Line,LONG Left,LONG Right)
  219. {
  220.     TextBufferInfo *BufferInfo;
  221.  
  222.     BufferInfo = Context->UserData;
  223.  
  224.     if(Line >= BufferInfo->TopLine && Line < BufferInfo->TopLine + BufferInfo->NumBufferLines && Line < Lines)
  225.     {
  226.         if(Left >= BufferInfo->NumBufferColumns)
  227.             return;
  228.  
  229.         if(Right >= BufferInfo->NumBufferColumns)
  230.             Right = BufferInfo->NumBufferColumns - 1;
  231.  
  232.         if(Left <= Right)
  233.             BufferComplement(BufferInfo,BufferInfo->BufferColumnOffsets[Left],BufferInfo->BufferLineOffsets[Line - BufferInfo->TopLine],BufferInfo->BufferColumnOffsets[Right - Left + 1],BufferInfo->BufferLineOffsets[1]);
  234.     }
  235. }
  236.  
  237.     /* Transfer the buffer contents line by line. */
  238.  
  239. STATIC BOOL
  240. Buffer_Put(APTR UserData,STRPTR Buffer,LONG Length)
  241. {
  242.     if(Length <= 0)
  243.         return(TRUE);
  244.     else
  245.     {
  246.         BOOL Result;
  247.  
  248.         if(Config->TerminalConfig->FontMode == FONT_STANDARD)
  249.             Result = (BOOL)(WriteChunkBytes(UserData,Buffer,Length) == Length);
  250.         else
  251.             Result = WriteTranslatedToClip(UserData,Buffer,Length);
  252.  
  253.         return(Result);
  254.     }
  255. }
  256.  
  257. STATIC BOOL
  258. Buffer_PutLine(APTR UserData,STRPTR Buffer,LONG Length)
  259. {
  260.     BOOL Result;
  261.  
  262.     if(Length <= 0)
  263.         Result = TRUE;
  264.     else
  265.     {
  266.         if(Config->TerminalConfig->FontMode == FONT_STANDARD)
  267.             Result = (BOOL)(WriteChunkBytes(UserData,Buffer,Length) == Length);
  268.         else
  269.             Result = WriteTranslatedToClip(UserData,Buffer,Length);
  270.     }
  271.  
  272.     if(Result)
  273.         Result = (BOOL)(WriteChunkBytes(UserData,"\n",1) == 1);
  274.  
  275.     return(Result);
  276. }
  277.  
  278. STATIC BOOL
  279. Buffer_Transfer(struct MarkerContext *Context,LONG Line,LONG Left,LONG Right,MARKER_Put Put,APTR UserData)
  280. {
  281.     TextBufferInfo *BufferInfo;
  282.     BOOL Result;
  283.  
  284.     BufferInfo = Context->UserData;
  285.     Result = TRUE;
  286.  
  287.     SafeObtainSemaphoreShared(&RasterSemaphore);
  288.  
  289.     if(Line >= 0 && Line < Lines)
  290.     {
  291.         STRPTR TheLine;
  292.  
  293.         TheLine = BufferLines[Line];
  294.  
  295.         if(Left < 0)
  296.             Left = 0;
  297.  
  298.         if(Right >= TheLine[-1])
  299.             Right = TheLine[-1] - 1;
  300.  
  301.         if(Left <= Right)
  302.             Result = Put(UserData,&TheLine[Left],Right - Left + 1);
  303.         else if (TheLine[-1] == 0)
  304.             Result = Put(UserData,&TheLine[Left],0);
  305.     }
  306.  
  307.     ReleaseSemaphore(&RasterSemaphore);
  308.  
  309.     return(Result);
  310. }
  311.  
  312. STATIC BOOL
  313. Buffer_PickWord(struct MarkerContext *UnusedContext,LONG Left,LONG Top,LONG *WordLeft,LONG *WordRight)
  314. {
  315.     BOOL GotIt;
  316.  
  317.     GotIt = FALSE;
  318.  
  319.     SafeObtainSemaphoreShared(&BufferSemaphore);
  320.  
  321.     if(Top >= 0 && Top < Lines)
  322.     {
  323.         STRPTR TheLine;
  324.  
  325.         TheLine = BufferLines[Top];
  326.  
  327.         if(Left >= 0 && Left < TheLine[-1] && TheLine[Left] != ' ')
  328.         {
  329.             LONG From,To;
  330.  
  331.             From = To = Left;
  332.  
  333.             while(From > 0 && TheLine[From - 1] != ' ')
  334.                 From--;
  335.  
  336.             while(To < TheLine[-1] - 1 && TheLine[To + 1] != ' ')
  337.                 To++;
  338.  
  339.             GotIt = TRUE;
  340.  
  341.             *WordLeft    = From;
  342.             *WordRight    = To;
  343.         }
  344.     }
  345.  
  346.     ReleaseSemaphore(&BufferSemaphore);
  347.  
  348.     return(GotIt);
  349. }
  350.  
  351. STATIC APTR
  352. Buffer_TransferStartStop(struct MarkerContext *Context,APTR UserData,ULONG Qualifier)
  353. {
  354.     struct IFFHandle *Handle;
  355.     TextBufferInfo *BufferInfo;
  356.  
  357.     BufferInfo = Context->UserData;
  358.  
  359.     if(Handle = UserData)
  360.     {
  361.         if(!PopChunk(Handle))
  362.             PopChunk(Handle);
  363.     }
  364.     else
  365.     {
  366.         APTR Buffer;
  367.         LONG Size;
  368.  
  369.         SafeObtainSemaphoreShared(&BufferSemaphore);
  370.  
  371.         SetWait(BufferInfo->Window);
  372.  
  373.         Buffer    = NULL;
  374.         Size    = 0;
  375.  
  376.         if(Qualifier & SHIFT_KEY)
  377.             GetClipContents(Config->ClipConfig->ClipboardUnit,&Buffer,&Size);
  378.  
  379.         if(Handle = OpenIFFClip(Config->ClipConfig->ClipboardUnit,MODE_NEWFILE))
  380.         {
  381.             if(!PushChunk(Handle,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN))
  382.             {
  383.                 if(!PushChunk(Handle,0,ID_CHRS,IFFSIZE_UNKNOWN))
  384.                 {
  385.                     if(Size > 0)
  386.                     {
  387.                         BOOL Ok;
  388.  
  389.                         Ok = (BOOL)(WriteChunkBytes(Handle,Buffer,Size) == Size);
  390.  
  391.                         FreeVecPooled(Buffer);
  392.  
  393.                         if(Ok)
  394.                             return(Handle);
  395.                     }
  396.                     else
  397.                         return(Handle);
  398.                 }
  399.             }
  400.         }
  401.     }
  402.  
  403.     CloseIFFClip(Handle);
  404.  
  405.     ReleaseSemaphore(&BufferSemaphore);
  406.  
  407.     ClrWait(BufferInfo->Window);
  408.  
  409.     return(NULL);
  410. }
  411.  
  412. STATIC VOID
  413. BufferMarkerStop(TextBufferInfo *BufferInfo)
  414. {
  415.     if(BufferInfo->Marker)
  416.     {
  417.         UpMarker(BufferInfo->Marker);
  418.  
  419.         FreeVecPooled(BufferInfo->Marker);
  420.         BufferInfo->Marker = NULL;
  421.  
  422.         ReportMouse(FALSE,BufferInfo->Window);
  423.  
  424.         ModifyIDCMP(BufferInfo->Window,BufferInfo->Window->IDCMPFlags & ~IDCMP_INTUITICKS);
  425.     }
  426.  
  427.     OffMenu(BufferInfo->Window,FULLMENUNUM(1,0,NOSUB));
  428.     OffMenu(BufferInfo->Window,FULLMENUNUM(1,2,NOSUB));
  429. }
  430.  
  431. STATIC VOID
  432. BufferSetMarker(TextBufferInfo *BufferInfo,LONG Left,LONG Top,LONG Width)
  433. {
  434.     BufferMarkerStop(BufferInfo);
  435.  
  436.     if(BufferInfo->Marker = CreateMarkerContext(
  437.         Buffer_AskPosition,
  438.         Buffer_Scroll,
  439.         Buffer_Highlight,
  440.         Buffer_Highlight,
  441.         Buffer_TransferStartStop,
  442.         Buffer_Transfer,
  443.         Buffer_Put,
  444.         Buffer_PutLine,
  445.         Buffer_PickWord
  446.     ))
  447.     {
  448.         BufferInfo->Marker->UserData = BufferInfo;
  449.  
  450.         SetMarker(BufferInfo->Marker,BufferInfo->TopLine,BufferInfo->DisplayedLines,Lines,0,BufferInfo->NumBufferColumns,BufferInfo->NumBufferColumns,Top,Left,Left + Width - 1);
  451.  
  452.         BufferMarkerInterrupt(BufferInfo);
  453.     }
  454. }
  455.  
  456. STATIC VOID
  457. BufferMarkerSelectAll(TextBufferInfo *BufferInfo)
  458. {
  459.     SafeObtainSemaphoreShared(&BufferSemaphore);
  460.  
  461.     if(Lines > 0)
  462.     {
  463.         BufferMarkerStop(BufferInfo);
  464.  
  465.         if(BufferInfo->Marker = CreateMarkerContext(
  466.             Buffer_AskPosition,
  467.             Buffer_Scroll,
  468.             Buffer_Highlight,
  469.             Buffer_Highlight,
  470.             Buffer_TransferStartStop,
  471.             Buffer_Transfer,
  472.             Buffer_Put,
  473.             Buffer_PutLine,
  474.             Buffer_PickWord
  475.         ))
  476.         {
  477.             BufferInfo->Marker->UserData = BufferInfo;
  478.  
  479.             SelectAllMarker(BufferInfo->Marker,BufferInfo->TopLine,BufferInfo->DisplayedLines,Lines,0,BufferInfo->NumBufferColumns,BufferInfo->NumBufferColumns,
  480.                 0,0,
  481.                 BufferInfo->NumBufferColumns - 1,Lines - 1
  482.             );
  483.  
  484.             BufferMarkerInterrupt(BufferInfo);
  485.         }
  486.     }
  487.  
  488.     ReleaseSemaphore(&BufferSemaphore);
  489. }
  490.  
  491. STATIC VOID
  492. BufferMarkWord(TextBufferInfo *BufferInfo)
  493. {
  494.     BufferMarkerStop(BufferInfo);
  495.  
  496.     if(BufferInfo->Marker = CreateMarkerContext(
  497.         Buffer_AskPosition,
  498.         Buffer_Scroll,
  499.         Buffer_Highlight,
  500.         Buffer_Highlight,
  501.         Buffer_TransferStartStop,
  502.         Buffer_Transfer,
  503.         Buffer_Put,
  504.         Buffer_PutLine,
  505.         Buffer_PickWord
  506.     ))
  507.     {
  508.         BufferInfo->Marker->UserData = BufferInfo;
  509.  
  510.         SafeObtainSemaphoreShared(&BufferSemaphore);
  511.  
  512.         if(!SetWordMarker(BufferInfo->Marker,BufferInfo->TopLine,BufferInfo->DisplayedLines,Lines,0,BufferInfo->NumBufferColumns,BufferInfo->NumBufferColumns))
  513.             BufferMarkerStop(BufferInfo);
  514.         else
  515.             BufferMarkerInterrupt(BufferInfo);
  516.  
  517.         ReleaseSemaphore(&BufferSemaphore);
  518.     }
  519. }
  520.  
  521. STATIC VOID
  522. BufferMarkerStart(TextBufferInfo *BufferInfo,UWORD MsgQualifier)
  523. {
  524.     if(BufferInfo->Marker && !(MsgQualifier & SHIFT_KEY))
  525.         BufferMarkerStop(BufferInfo);
  526.  
  527.     BufferInfo->Interrupted = FALSE;
  528.  
  529.     if(BufferInfo->Marker)
  530.         MoveMouseMarker(BufferInfo->Marker);
  531.     else
  532.     {
  533.         if(BufferInfo->Marker = CreateMarkerContext(
  534.             Buffer_AskPosition,
  535.             Buffer_Scroll,
  536.             Buffer_Highlight,
  537.             Buffer_Highlight,
  538.             Buffer_TransferStartStop,
  539.             Buffer_Transfer,
  540.             Buffer_Put,
  541.             Buffer_PutLine,
  542.             Buffer_PickWord
  543.         ))
  544.         {
  545.             BufferInfo->Marker->UserData = BufferInfo;
  546.  
  547.             SafeObtainSemaphoreShared(&BufferSemaphore);
  548.  
  549.             DownMarker(BufferInfo->Marker,BufferInfo->TopLine,BufferInfo->DisplayedLines,Lines,0,BufferInfo->NumBufferColumns,BufferInfo->NumBufferColumns);
  550.  
  551.             ReleaseSemaphore(&BufferSemaphore);
  552.         }
  553.     }
  554.  
  555.     if(BufferInfo->Marker)
  556.     {
  557.         ReportMouse(TRUE,BufferInfo->Window);
  558.         ModifyIDCMP(BufferInfo->Window,BufferInfo->Window->IDCMPFlags | IDCMP_INTUITICKS);
  559.     }
  560. }
  561.  
  562. STATIC VOID
  563. BufferMarkerInterrupt(TextBufferInfo *BufferInfo)
  564. {
  565.     if(CheckMarker(BufferInfo->Marker))
  566.     {
  567.         OnMenu(BufferInfo->Window,FULLMENUNUM(1,0,NOSUB));
  568.         OnMenu(BufferInfo->Window,FULLMENUNUM(1,2,NOSUB));
  569.     }
  570.     else
  571.     {
  572.         OffMenu(BufferInfo->Window,FULLMENUNUM(1,0,NOSUB));
  573.         OffMenu(BufferInfo->Window,FULLMENUNUM(1,2,NOSUB));
  574.     }
  575.  
  576.     BufferInfo->Interrupted = TRUE;
  577.  
  578.     ReportMouse(FALSE,BufferInfo->Window);
  579.     ModifyIDCMP(BufferInfo->Window,BufferInfo->Window->IDCMPFlags & ~IDCMP_INTUITICKS);
  580. }
  581.  
  582. STATIC VOID
  583. BufferMarkerMoveMouse(TextBufferInfo *BufferInfo)
  584. {
  585.     if(BufferInfo->Marker && !BufferInfo->Interrupted)
  586.         MoveMouseMarker(BufferInfo->Marker);
  587. }
  588.  
  589. STATIC VOID
  590. BufferMarkerTransfer(TextBufferInfo *BufferInfo,UWORD MsgQualifier)
  591. {
  592.     if(BufferInfo->Marker)
  593.     {
  594.         TransferMarker(BufferInfo->Marker,MsgQualifier);
  595.  
  596.         BufferMarkerStop(BufferInfo);
  597.     }
  598. }
  599.  
  600. /****************************************************************************/
  601.  
  602.     /* FlushMsg(struct Window *Window):
  603.      *
  604.      *    Cancel all pending messages of a window.
  605.      */
  606.  
  607. STATIC VOID
  608. FlushMsg(struct Window *Window)
  609. {
  610.     struct Message *Message;
  611.  
  612.     while(Message = GetMsg(Window->UserPort))
  613.         ReplyMsg(Message);
  614. }
  615.  
  616. STATIC VOID
  617. BufferClear(TextBufferInfo *BufferInfo,LONG Left,LONG Top,LONG Right,LONG Bottom)
  618. {
  619.     struct RastPort    *RPort = BufferInfo->RPort;
  620.  
  621.     Left    += BufferInfo->Left;
  622.     Top        += BufferInfo->Top;
  623.     Right    += BufferInfo->Left;
  624.     Bottom    += BufferInfo->Top;
  625.  
  626.     if(Right >= BufferInfo->Left + BufferInfo->Width)
  627.         Right = BufferInfo->Left + BufferInfo->Width - 1;
  628.  
  629.     if(Bottom >= BufferInfo->Top + BufferInfo->Height)
  630.         Bottom = BufferInfo->Top + BufferInfo->Height - 1;
  631.  
  632.     if(Left <= Right && Top <= Bottom)
  633.         EraseRect(RPort,Left,Top,Right,Bottom);
  634. }
  635.  
  636. STATIC VOID
  637. BufferScroll(TextBufferInfo *BufferInfo,LONG Lines)
  638. {
  639.     struct RastPort *RPort;
  640.  
  641.     if(Lines < 0)
  642.         Lines = -BufferInfo->BufferLineOffsets[-Lines];
  643.     else
  644.         Lines = BufferInfo->BufferLineOffsets[Lines];
  645.  
  646.     RPort = BufferInfo->RPort;
  647.  
  648.     ScrollRaster(RPort,0,Lines,BufferInfo->Left,BufferInfo->Top,BufferInfo->Left + BufferInfo->Width - 1,BufferInfo->Top + BufferInfo->Height - 1);
  649.  
  650.     BeginUpdate(RPort->Layer);
  651.     EndUpdate(RPort->Layer,TRUE);
  652. }
  653.  
  654. STATIC VOID
  655. BufferComplement(TextBufferInfo *BufferInfo,LONG SrcX,LONG SrcY,LONG Width,LONG Height)
  656. {
  657.     struct RastPort *RPort = BufferInfo->RPort;
  658.  
  659.     SetPens(RPort,(ULONG)~0,0,JAM1 | COMPLEMENT);
  660.  
  661.     SrcX += BufferInfo->Left;
  662.     SrcY += BufferInfo->Top;
  663.  
  664.     FillBox(RPort,SrcX,SrcY,Width,Height);
  665.  
  666.     SetPens(RPort,BufferInfo->TextFrontPen,BufferInfo->TextBackPen,JAM2);
  667. }
  668.  
  669.     /* DeleteScroller():
  670.      *
  671.      *    Delete scroller and arrow objects.
  672.      */
  673.  
  674. STATIC VOID
  675. DeleteScroller(TextBufferInfo *BufferInfo)
  676. {
  677.     DisposeObject(BufferInfo->Scroller);
  678.     DisposeObject(BufferInfo->UpArrow);
  679.     DisposeObject(BufferInfo->DownArrow);
  680.     DisposeObject(BufferInfo->UpImage);
  681.     DisposeObject(BufferInfo->DownImage);
  682. }
  683.  
  684.     /* CreateScroller(LONG Height):
  685.      *
  686.      *    Create scroller and arrow objects.
  687.      */
  688.  
  689. STATIC BOOL
  690. CreateScroller(TextBufferInfo *BufferInfo,LONG Height)
  691. {
  692.     STATIC struct TagItem ArrowMappings[] =
  693.     {
  694.         GA_ID,    GA_ID,
  695.  
  696.         TAG_END
  697.     };
  698.  
  699.     ULONG ArrowWidth,ArrowHeight;
  700.     struct Screen *Screen;
  701.     LONG SizeType;
  702.     BOOL Result;
  703.  
  704.     Result = FALSE;
  705.  
  706.     if(BufferInfo->Parent)
  707.         Screen = BufferInfo->Parent;
  708.     else
  709.         Screen = BufferInfo->Screen;
  710.  
  711.     if(Screen->Flags & SCREENHIRES)
  712.         SizeType = SYSISIZE_MEDRES;
  713.     else
  714.         SizeType = SYSISIZE_LOWRES;
  715.  
  716.     if(!BufferInfo->Parent)
  717.     {
  718.         if(BufferInfo->UpImage = NewObject(NULL,SYSICLASS,
  719.             SYSIA_Size,        SizeType,
  720.             SYSIA_Which,    UPIMAGE,
  721.             SYSIA_DrawInfo,    BufferInfo->BufferDrawInfo,
  722.         TAG_DONE))
  723.         {
  724.             if(BufferInfo->DownImage = NewObject(NULL,SYSICLASS,
  725.                 SYSIA_Size,        SizeType,
  726.                 SYSIA_Which,    DOWNIMAGE,
  727.                 SYSIA_DrawInfo,    BufferInfo->BufferDrawInfo,
  728.             TAG_DONE))
  729.             {
  730.                 LONG ScrollerHeight,LeftEdge;
  731.  
  732.                 GetAttr(IA_Height,    BufferInfo->UpImage,&ArrowHeight);
  733.                 GetAttr(IA_Width,    BufferInfo->UpImage,&ArrowWidth);
  734.  
  735.                 ScrollerHeight = Height - 2 * ArrowHeight;
  736.  
  737.                 LeftEdge = BufferInfo->Screen->Width - ArrowWidth;
  738.  
  739.                 if(BufferInfo->Scroller = NewObject(NULL,PROPGCLASS,
  740.                     GA_ID,            GAD_SCROLLER,
  741.  
  742.                     GA_Top,            0,
  743.                     GA_Left,        LeftEdge,
  744.                     GA_Width,        ArrowWidth,
  745.                     GA_Height,        ScrollerHeight,
  746.                     GA_Immediate,    TRUE,
  747.                     GA_FollowMouse,    TRUE,
  748.                     GA_RelVerify,    TRUE,
  749.  
  750.                     PGA_Freedom,    FREEVERT,
  751.                     PGA_NewLook,    TRUE,
  752.  
  753.                     PGA_Visible,    1,
  754.                     PGA_Total,        1,
  755.                 TAG_DONE))
  756.                 {
  757.                     if(BufferInfo->UpArrow = NewObject(NULL,BUTTONGCLASS,
  758.                         GA_ID,            GAD_UP,
  759.                         GA_Image,        BufferInfo->UpImage,
  760.                         GA_Left,        LeftEdge,
  761.                         GA_Top,            ScrollerHeight,
  762.                         GA_Height,        ArrowHeight,
  763.                         GA_Width,        ArrowWidth,
  764.                         GA_Previous,    BufferInfo->Scroller,
  765.  
  766.                         ICA_TARGET,        ICTARGET_IDCMP,
  767.                         ICA_MAP,        ArrowMappings,
  768.                     TAG_DONE))
  769.                     {
  770.                         if(BufferInfo->DownArrow = NewObject(NULL,BUTTONGCLASS,
  771.                             GA_ID,            GAD_DOWN,
  772.                             GA_Image,        BufferInfo->DownImage,
  773.                             GA_Left,        LeftEdge,
  774.                             GA_Top,            ScrollerHeight + ArrowHeight,
  775.                             GA_Height,        ArrowHeight,
  776.                             GA_Width,        ArrowWidth,
  777.                             GA_Previous,    BufferInfo->UpArrow,
  778.  
  779.                             ICA_TARGET,        ICTARGET_IDCMP,
  780.                             ICA_MAP,        ArrowMappings,
  781.                         TAG_DONE))
  782.                             Result = TRUE;
  783.                     }
  784.                 }
  785.             }
  786.         }
  787.     }
  788.     else
  789.     {
  790.         Object *SizeImage;
  791.  
  792.         if(SizeImage = NewObject(NULL,SYSICLASS,
  793.             SYSIA_Size,        SizeType,
  794.             SYSIA_Which,    SIZEIMAGE,
  795.             SYSIA_DrawInfo,    BufferInfo->BufferDrawInfo,
  796.         TAG_DONE))
  797.         {
  798.             ULONG SizeWidth,SizeHeight;
  799.  
  800.             GetAttr(IA_Width,    SizeImage,&SizeWidth);
  801.             GetAttr(IA_Height,    SizeImage,&SizeHeight);
  802.  
  803.             DisposeObject(SizeImage);
  804.  
  805.             BufferInfo->RightBorderWidth = SizeWidth;
  806.  
  807.             if(BufferInfo->UpImage = NewObject(NULL,SYSICLASS,
  808.                 SYSIA_Size,        SizeType,
  809.                 SYSIA_Which,    UPIMAGE,
  810.                 SYSIA_DrawInfo,    BufferInfo->BufferDrawInfo,
  811.             TAG_DONE))
  812.             {
  813.                 GetAttr(IA_Height,BufferInfo->UpImage,&ArrowHeight);
  814.  
  815.                 if(BufferInfo->DownImage = NewObject(NULL,SYSICLASS,
  816.                     SYSIA_Size,        SizeType,
  817.                     SYSIA_Which,    DOWNIMAGE,
  818.                     SYSIA_DrawInfo,    BufferInfo->BufferDrawInfo,
  819.                 TAG_DONE))
  820.                 {
  821.                     if(BufferInfo->Scroller = NewObject(NULL,PROPGCLASS,
  822.                         GA_ID,            GAD_SCROLLER,
  823.  
  824.                         GA_Top,            Screen->WBorTop + Screen->Font->ta_YSize + 2,
  825.                         GA_RelHeight,    -(Screen->WBorTop + Screen->Font->ta_YSize + 2 + SizeHeight + 1 + 2 * ArrowHeight),
  826.                         GA_Width,        SizeWidth - 8,
  827.                         GA_RelRight,    -(SizeWidth - 5),
  828.  
  829.                         GA_Immediate,    TRUE,
  830.                         GA_FollowMouse,    TRUE,
  831.                         GA_RelVerify,    TRUE,
  832.                         GA_RightBorder,    TRUE,
  833.  
  834.                         PGA_Freedom,    FREEVERT,
  835.                         PGA_NewLook,    TRUE,
  836.                         PGA_Borderless,    TRUE,
  837.  
  838.                         PGA_Visible,    1,
  839.                         PGA_Total,        1,
  840.                     TAG_DONE))
  841.                     {
  842.                         if(BufferInfo->UpArrow = NewObject(NULL,BUTTONGCLASS,
  843.                             GA_ID,            GAD_UP,
  844.  
  845.                             GA_Image,        BufferInfo->UpImage,
  846.                             GA_RelRight,    -(SizeWidth - 1),
  847.                             GA_RelBottom,    -(SizeHeight - 1 + 2 * ArrowHeight),
  848.                             GA_Height,        ArrowHeight,
  849.                             GA_Width,        SizeWidth,
  850.                             GA_Previous,    BufferInfo->Scroller,
  851.                             GA_RightBorder,    TRUE,
  852.  
  853.                             ICA_TARGET,        ICTARGET_IDCMP,
  854.                             ICA_MAP,        ArrowMappings,
  855.                         TAG_DONE))
  856.                         {
  857.                             if(BufferInfo->DownArrow = NewObject(NULL,BUTTONGCLASS,
  858.                                 GA_ID,            GAD_DOWN,
  859.  
  860.                                 GA_Image,        BufferInfo->DownImage,
  861.                                 GA_RelRight,    -(SizeWidth - 1),
  862.                                 GA_RelBottom,    -(SizeHeight - 1 + ArrowHeight),
  863.                                 GA_Height,        ArrowHeight,
  864.                                 GA_Width,        SizeWidth,
  865.                                 GA_Previous,    BufferInfo->UpArrow,
  866.                                 GA_RightBorder,    TRUE,
  867.  
  868.                                 ICA_TARGET,        ICTARGET_IDCMP,
  869.                                 ICA_MAP,        ArrowMappings,
  870.                             TAG_DONE))
  871.                                 Result = TRUE;
  872.                         }
  873.                     }
  874.                 }
  875.             }
  876.         }
  877.     }
  878.  
  879.     if(!Result)
  880.         DeleteScroller(BufferInfo);
  881.     else
  882.         BufferInfo->ArrowWidth = ArrowWidth;
  883.  
  884.     return(Result);
  885. }
  886.  
  887.     /* PrintLine(STRPTR Buffer,LONG LineNumber):
  888.      *
  889.      *    Print a line at a given line number in the displayed area.
  890.      */
  891.  
  892. STATIC VOID
  893. PrintLine(TextBufferInfo *BufferInfo,STRPTR Buffer,LONG LineNumber)
  894. {
  895.     LONG Length;
  896.  
  897.     Length = Buffer[-1];
  898.  
  899.         /* Print the text. */
  900.  
  901.     if(Length > 0)
  902.     {
  903.         struct TextExtent Extent;
  904.  
  905.         Length = TextFit(BufferInfo->RPort,Buffer,Length,&Extent,NULL,1,BufferInfo->Width,32767);
  906.  
  907.         if(Length > 0)
  908.             PlaceText(BufferInfo->RPort,BufferInfo->Left,BufferInfo->Top + BufferInfo->BufferLineOffsets[LineNumber],Buffer,Length);
  909.     }
  910.  
  911.         /* The line doesn't exactly fill the displayed line,
  912.          * so erase the remaining columns.
  913.          */
  914.  
  915.     if(Length < BufferInfo->NumBufferColumns)
  916.         BufferClear(BufferInfo,BufferInfo->BufferColumnOffsets[Length],BufferInfo->BufferLineOffsets[LineNumber],BufferInfo->BufferColumnOffsets[BufferInfo->NumBufferColumns] - 1,BufferInfo->BufferLineOffsets[LineNumber + 1] - 1);
  917. }
  918.  
  919. STATIC VOID
  920. PrintLineWithMarker(TextBufferInfo *BufferInfo,STRPTR Buffer,LONG LineNumber,LONG AbsoluteLine)
  921. {
  922.     LONG Length,Left,Right;
  923.  
  924.     Length = Buffer[-1];
  925.  
  926.         /* Print the text. */
  927.  
  928.     if(Length > 0)
  929.     {
  930.         struct TextExtent Extent;
  931.  
  932.         Length = TextFit(BufferInfo->RPort,Buffer,Length,&Extent,NULL,1,BufferInfo->Width,32767);
  933.  
  934.         if(Length > 0)
  935.             PlaceText(BufferInfo->RPort,BufferInfo->Left,BufferInfo->Top + BufferInfo->BufferLineOffsets[LineNumber],Buffer,Length);
  936.     }
  937.  
  938.         /* The line doesn't exactly fill the displayed line,
  939.          * so erase the remaining columns.
  940.          */
  941.  
  942.     if(Length < BufferInfo->NumBufferColumns)
  943.         BufferClear(BufferInfo,BufferInfo->BufferColumnOffsets[Length],BufferInfo->BufferLineOffsets[LineNumber],BufferInfo->BufferColumnOffsets[BufferInfo->NumBufferColumns] - 1,BufferInfo->BufferLineOffsets[LineNumber + 1] - 1);
  944.  
  945.     if(CheckMarkerHighlighting(BufferInfo->Marker,AbsoluteLine,&Left,&Right))
  946.     {
  947.         if(Left < BufferInfo->NumBufferColumns)
  948.         {
  949.             if(Right >= BufferInfo->NumBufferColumns)
  950.                 Right = BufferInfo->NumBufferColumns - 1;
  951.  
  952.             if(Left <= Right)
  953.                 BufferComplement(BufferInfo,BufferInfo->BufferColumnOffsets[Left],BufferInfo->BufferLineOffsets[LineNumber],BufferInfo->BufferColumnOffsets[Right - Left + 1],BufferInfo->BufferLineOffsets[1]);
  954.         }
  955.     }
  956. }
  957.  
  958.     /* RedrawScreen(LONG FirstLine):
  959.      *
  960.      *    Redraw the contents of the entire screen and return the
  961.      *    number of lines actually drawn.
  962.      */
  963.  
  964. STATIC LONG
  965. RedrawScreen(TextBufferInfo *BufferInfo,LONG FirstLine)
  966. {
  967.     LONG i,Last,Line = 0,Result;
  968.  
  969.     SafeObtainSemaphoreShared(&BufferSemaphore);
  970.  
  971.         /* Determine last line to display. */
  972.  
  973.     if((Last = FirstLine + BufferInfo->NumBufferLines) > Lines)
  974.     {
  975.         Last = Lines;
  976.  
  977.         if((FirstLine = Last - BufferInfo->NumBufferLines) < 0)
  978.             FirstLine = 0;
  979.  
  980.         BufferInfo->TopLine = FirstLine;
  981.     }
  982.  
  983.     if(Last > FirstLine + BufferInfo->NumBufferLines)
  984.         Last = FirstLine + BufferInfo->NumBufferLines;
  985.  
  986.     Result = Last - FirstLine;
  987.  
  988.     if(Lines)
  989.     {
  990.         if(BufferInfo->LastTopLine == -1)
  991.             BufferInfo->LastTopLine = FirstLine;
  992.         else
  993.         {
  994.             LONG Delta = FirstLine - BufferInfo->LastTopLine;
  995.  
  996.             if(ABS(Delta) >= BufferInfo->NumBufferLines)
  997.                 BufferInfo->LastTopLine = FirstLine;
  998.             else
  999.             {
  1000.                     /* No change? */
  1001.  
  1002.                 if(!Delta)
  1003.                 {
  1004.                     ReleaseSemaphore(&BufferSemaphore);
  1005.  
  1006.                     return(Result);
  1007.                 }
  1008.                 else
  1009.                 {
  1010.                     BufferInfo->LastTopLine = FirstLine;
  1011.  
  1012.                         /* Scrolled up? */
  1013.  
  1014.                     if(Delta < 0)
  1015.                     {
  1016.                         BufferScroll(BufferInfo,Delta);
  1017.  
  1018.                         Last = FirstLine - Delta;
  1019.                     }
  1020.                     else
  1021.                     {
  1022.                             /* Scrolled down. */
  1023.  
  1024.                         BufferScroll(BufferInfo,Delta);
  1025.  
  1026.                         FirstLine += BufferInfo->NumBufferLines - Delta;
  1027.  
  1028.                         Line = BufferInfo->NumBufferLines - Delta;
  1029.                     }
  1030.                 }
  1031.             }
  1032.         }
  1033.  
  1034.         if(BufferLines)
  1035.         {
  1036.             if(BufferInfo->Marker)
  1037.             {
  1038.                 for(i = FirstLine ; i < Last ; i++)
  1039.                     PrintLineWithMarker(BufferInfo,BufferLines[i],Line++,i);
  1040.             }
  1041.             else
  1042.             {
  1043.                 for(i = FirstLine ; i < Last ; i++)
  1044.                     PrintLine(BufferInfo,BufferLines[i],Line++);
  1045.             }
  1046.         }
  1047.     }
  1048.  
  1049.         /* We didn't fill the whole screen, so clear the rest. */
  1050.  
  1051.     if(Result < BufferInfo->NumBufferLines)
  1052.         BufferClear(BufferInfo,0,BufferInfo->BufferLineOffsets[Result],BufferInfo->BufferColumnOffsets[BufferInfo->NumBufferColumns] - 1,BufferInfo->BufferLineOffsets[BufferInfo->NumBufferLines] - 1);
  1053.  
  1054.     ReleaseSemaphore(&BufferSemaphore);
  1055.  
  1056.     return(Result);
  1057. }
  1058.  
  1059. STATIC VOID
  1060. BufferDestructor(struct DataMsg *Item)
  1061. {
  1062.     Signal(Item->Client,Item->Mask);
  1063. }
  1064.  
  1065. STATIC VOID
  1066. BufferSerWrite(TextBufferInfo *BufferInfo,APTR Data,LONG Size)
  1067. {
  1068.     struct DataMsg Msg;
  1069.  
  1070.     InitMsgItem(&Msg,(DESTRUCTOR)BufferDestructor);
  1071.  
  1072.     Msg.Type    = DATAMSGTYPE_WRITE;
  1073.     Msg.Data    = Data;
  1074.     Msg.Size    = Size;
  1075.     Msg.Client    = FindTask(NULL);
  1076.     Msg.Mask    = 1UL << BufferInfo->BufferSignal;
  1077.  
  1078.     Forbid();
  1079.  
  1080.     ClrSignal(Msg.Mask);
  1081.  
  1082.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1083.  
  1084.     Wait(Msg.Mask);
  1085.  
  1086.     Permit();
  1087. }
  1088.  
  1089. STATIC VOID
  1090. StartSearch(TextBufferInfo *BufferInfo,struct SearchInfo *SearchInfo,STRPTR SearchBuffer)
  1091. {
  1092.     SafeObtainSemaphoreShared(&BufferSemaphore);
  1093.  
  1094.     LT_LockWindow(BufferInfo->Window);
  1095.  
  1096.     if(Lines)
  1097.     {
  1098.         LONG LineNumber;
  1099.  
  1100.         LineNumber = SearchTextBuffer(SearchInfo);
  1101.  
  1102.         BufferMarkerStop(BufferInfo);
  1103.  
  1104.         if(LineNumber == -1)
  1105.         {
  1106.             ShowRequest(BufferInfo->Window,LocaleString(MSG_TERMBUFFER_DID_NOT_FIND_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SearchBuffer);
  1107.  
  1108.             FlushMsg(BufferInfo->Window);
  1109.  
  1110.             SearchInfo->FoundY = -1;
  1111.         }
  1112.         else
  1113.         {
  1114.             if(LineNumber < BufferInfo->TopLine)
  1115.             {
  1116.                 BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine = LineNumber);
  1117.  
  1118.                 SetGadgetAttrs((struct Gadget *)BufferInfo->Scroller,BufferInfo->Window,NULL,
  1119.                     PGA_Top,BufferInfo->TopLine,
  1120.                 TAG_DONE);
  1121.             }
  1122.             else
  1123.             {
  1124.                 if(LineNumber > BufferInfo->TopLine + BufferInfo->DisplayedLines - 1)
  1125.                 {
  1126.                     if(LineNumber >= Lines - BufferInfo->NumBufferLines)
  1127.                     {
  1128.                         LONG NewCurrentLine;
  1129.  
  1130.                         if((NewCurrentLine = Lines - BufferInfo->NumBufferLines) < 0)
  1131.                             NewCurrentLine = 0;
  1132.  
  1133.                         if(BufferInfo->TopLine != NewCurrentLine)
  1134.                             BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine = NewCurrentLine);
  1135.                     }
  1136.                     else
  1137.                         BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine = LineNumber);
  1138.  
  1139.                     SetGadgetAttrs((struct Gadget *)BufferInfo->Scroller,BufferInfo->Window,NULL,
  1140.                         PGA_Top,BufferInfo->TopLine,
  1141.                     TAG_DONE);
  1142.                 }
  1143.             }
  1144.  
  1145.             BufferSetMarker(BufferInfo,SearchInfo->FoundX,LineNumber,SearchInfo->PatternWidth);
  1146.         }
  1147.     }
  1148.     else
  1149.         ShowRequest(BufferInfo->Window,LocaleString(MSG_GLOBAL_NOTHING_IN_THE_BUFFER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
  1150.  
  1151.     LT_UnlockWindow(BufferInfo->Window);
  1152.  
  1153.     ReleaseSemaphore(&BufferSemaphore);
  1154. }
  1155.  
  1156. STATIC BOOL
  1157. HandleBuffer(struct SignalSemaphore *Access,TextBufferInfo **Data)
  1158. {
  1159.     ULONG LastSeconds,LastMicros,Seconds,Micros;
  1160.     BOOL WindowJustActivated,UpdatePercent,RingBack;
  1161.     ULONG SignalSet;
  1162.     struct IntuiMessage *Message;
  1163.     ULONG MsgClass;
  1164.     UWORD MsgCode,MsgQualifier,MsgGadgetID;
  1165.     LONG MouseX,MouseY;
  1166.     UBYTE Char,FullChar;
  1167.     UBYTE PercentBuffer[80],SearchBuffer[256];
  1168.     STRPTR PercentTemplate;
  1169.     struct SearchContext *Context;
  1170.     struct SearchInfo *SearchInfo;
  1171.     struct Hook HistoryHook;
  1172.     TextBufferInfo *BufferInfo;
  1173.     BOOL DisplayDirty,DoNotUpdateScroller;
  1174.     LONG NewTopLine;
  1175.     ULONG ClickSeconds,ClickMicros;
  1176.     BOOL TestingDoubleClick;
  1177.  
  1178.     TestingDoubleClick    = FALSE;
  1179.     ClickSeconds        = 0;
  1180.     ClickMicros            = 0;
  1181.  
  1182.     LastSeconds            = 0;
  1183.     LastMicros            = 0;
  1184.     UpdatePercent        = TRUE;
  1185.     RingBack             = FALSE;
  1186.  
  1187.     Context                = NULL;
  1188.     SearchInfo            = NULL;
  1189.  
  1190.     DoNotUpdateScroller    = FALSE;
  1191.     DisplayDirty        = FALSE;
  1192.     NewTopLine            = 0;
  1193.  
  1194.     BufferInfo = *Data;
  1195.  
  1196.     if(LocaleBase)
  1197.         PercentTemplate = "%lD/%lD (%ld%%)";
  1198.     else
  1199.         PercentTemplate = "%ld/%ld (%ld%%)";
  1200.  
  1201.     while(TRUE)
  1202.     {
  1203.         if(DisplayDirty)
  1204.         {
  1205.             DisplayDirty = FALSE;
  1206.  
  1207.             if(NewTopLine < 0)
  1208.                 NewTopLine = 0;
  1209.             else if (NewTopLine + BufferInfo->NumBufferLines >= Lines)
  1210.                 NewTopLine = Lines - BufferInfo->NumBufferLines;
  1211.  
  1212.             if(NewTopLine >= 0 && NewTopLine != BufferInfo->TopLine)
  1213.             {
  1214.                 BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,NewTopLine);
  1215.  
  1216.                 BufferInfo->TopLine = NewTopLine;
  1217.  
  1218.                 if(DoNotUpdateScroller)
  1219.                     DoNotUpdateScroller    = FALSE;
  1220.                 else
  1221.                 {
  1222.                     SetGadgetAttrs((struct Gadget *)BufferInfo->Scroller,BufferInfo->Window,NULL,
  1223.                         PGA_Top,BufferInfo->TopLine,
  1224.                     TAG_DONE);
  1225.                 }
  1226.  
  1227.                 UpdatePercent = TRUE;
  1228.             }
  1229.         }
  1230.  
  1231.         if(BufferInfo->TopLine < 0)
  1232.             BufferInfo->TopLine = 0;
  1233.  
  1234.             /* Show where we are. */
  1235.  
  1236.         if(UpdatePercent)
  1237.         {
  1238.             STRPTR ScreenTitle,WindowTitle;
  1239.  
  1240.             SafeObtainSemaphoreShared(&BufferSemaphore);
  1241.  
  1242.             if(Lines > 0)
  1243.                 LimitedSPrintf(sizeof(PercentBuffer),PercentBuffer,PercentTemplate,BufferInfo->TopLine,MAX(0,Lines - BufferInfo->NumBufferLines),(100 * (BufferInfo->TopLine + BufferInfo->DisplayedLines)) / Lines);
  1244.             else
  1245.                 PercentBuffer[0] = 0;
  1246.  
  1247.             LimitedSPrintf(sizeof(BufferInfo->TitleBuffer),BufferInfo->TitleBuffer,"%s  %s",LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),PercentBuffer);
  1248.  
  1249.             if(BufferInfo->Parent)
  1250.             {
  1251.                 WindowTitle    = BufferInfo->TitleBuffer;
  1252.                 ScreenTitle = (STRPTR)~0;
  1253.             }
  1254.             else
  1255.                 ScreenTitle = WindowTitle = BufferInfo->TitleBuffer;
  1256.  
  1257.             SetWindowTitles(BufferInfo->Window,WindowTitle,ScreenTitle);
  1258.  
  1259.             UpdatePercent = FALSE;
  1260.  
  1261.             ReleaseSemaphore(&BufferSemaphore);
  1262.         }
  1263.  
  1264.         if(!BufferInfo->BufferTerminated)
  1265.             SignalSet = Wait(SIG_KILL | SIG_TOFRONT | SIG_UPDATE | SIG_MOVEUP | PORTMASK(BufferInfo->Window->UserPort) | BufferInfo->QueueMask);
  1266.         else
  1267.         {
  1268.             ObtainSemaphore(Access);
  1269.  
  1270.             SignalSet = SIG_KILL | SIG_TOFRONT | SIG_UPDATE | SIG_MOVEUP | PORTMASK(BufferInfo->Window->UserPort) | BufferInfo->QueueMask;
  1271.             SignalSet = SetSignal(0,SignalSet) & SignalSet;
  1272.  
  1273.                 /* Disconnect */
  1274.  
  1275.             if(!SignalSet)
  1276.             {
  1277.                 BufferInfo->Buddy = NULL;
  1278.  
  1279.                 *Data = NULL;
  1280.  
  1281.                 ReleaseSemaphore(Access);
  1282.  
  1283.                 break;
  1284.             }
  1285.             else
  1286.                 ReleaseSemaphore(Access);
  1287.         }
  1288.  
  1289.             /* Leave this town? */
  1290.  
  1291.         if(SignalSet & SIG_KILL)
  1292.             BufferInfo->BufferTerminated = RingBack = TRUE;
  1293.  
  1294.             /* Bring our window to the front. */
  1295.  
  1296.         if(SignalSet & SIG_TOFRONT)
  1297.         {
  1298.             if(Context)
  1299.                 LT_ShowWindow(Context->SearchHandle,TRUE);
  1300.  
  1301.             BumpWindow(BufferInfo->Window);
  1302.         }
  1303.  
  1304.             /* Redraw the entire screen. */
  1305.  
  1306.         if(SignalSet & SIG_MOVEUP)
  1307.         {
  1308.             BufferMarkerStop(BufferInfo);
  1309.  
  1310.             BufferInfo->LastTopLine = -1;
  1311.  
  1312.             SafeObtainSemaphoreShared(&BufferSemaphore);
  1313.  
  1314.             BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine);
  1315.  
  1316.             SetGadgetAttrs((struct Gadget *)BufferInfo->Scroller,BufferInfo->Window,NULL,
  1317.                 PGA_Total,Lines,
  1318.             TAG_DONE);
  1319.  
  1320.             ReleaseSemaphore(&BufferSemaphore);
  1321.  
  1322.             UpdatePercent = TRUE;
  1323.  
  1324.             Signal((struct Task *)ThisProcess,SIG_HANDSHAKE);
  1325.         }
  1326.  
  1327.             /* Redraw the entire screen unless it is already drawn. */
  1328.  
  1329.         if(SignalSet & SIG_UPDATE)
  1330.         {
  1331.             SafeObtainSemaphoreShared(&BufferSemaphore);
  1332.  
  1333.             if(BufferInfo->DisplayedLines < BufferInfo->NumBufferLines || !Lines)
  1334.             {
  1335.                 BufferMarkerStop(BufferInfo);
  1336.  
  1337.                 BufferInfo->LastTopLine = -1;
  1338.  
  1339.                 BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine);
  1340.             }
  1341.  
  1342.             SetGadgetAttrs((struct Gadget *)BufferInfo->Scroller,BufferInfo->Window,NULL,
  1343.                 PGA_Total,Lines,
  1344.             TAG_DONE);
  1345.  
  1346.             ReleaseSemaphore(&BufferSemaphore);
  1347.  
  1348.             UpdatePercent = TRUE;
  1349.  
  1350.             Signal((struct Task *)ThisProcess,SIG_HANDSHAKE);
  1351.         }
  1352.  
  1353.             /* A request from the queue? */
  1354.  
  1355.         if(SignalSet & BufferInfo->QueueMask)
  1356.         {
  1357.             struct DataMsg *Msg;
  1358.  
  1359.             while(Msg = (struct DataMsg *)GetMsgItem(BufferInfo->Queue))
  1360.             {
  1361.                 switch(Msg->Size)
  1362.                 {
  1363.                     case REVIEW_MOVE_TOP:
  1364.  
  1365.                         DisplayDirty    = TRUE;
  1366.                         NewTopLine        = 0;
  1367.  
  1368.                         break;
  1369.  
  1370.                     case REVIEW_MOVE_BOTTOM:
  1371.  
  1372.                         DisplayDirty    = TRUE;
  1373.                         NewTopLine        = Lines - BufferInfo->NumBufferLines;
  1374.  
  1375.                         break;
  1376.  
  1377.                     case REVIEW_MOVE_UP:
  1378.  
  1379.                         DisplayDirty    = TRUE;
  1380.                         NewTopLine        = BufferInfo->TopLine - (BufferInfo->NumBufferLines - 1);
  1381.  
  1382.                         break;
  1383.  
  1384.                     case REVIEW_MOVE_DOWN:
  1385.  
  1386.                         DisplayDirty    = TRUE;
  1387.                         NewTopLine        = BufferInfo->TopLine + (BufferInfo->NumBufferLines - 1);
  1388.  
  1389.                         break;
  1390.                 }
  1391.  
  1392.                 DeleteMsgItem((struct MsgItem *)Msg);
  1393.             }
  1394.         }
  1395.  
  1396.             /* Process the incoming window
  1397.              * input.
  1398.              */
  1399.  
  1400.         while(Message = (struct IntuiMessage *)GetMsg(BufferInfo->Window->UserPort))
  1401.         {
  1402.             if(Context && Context->SearchWindow == Message->IDCMPWindow)
  1403.             {
  1404.                 MsgClass = NULL;
  1405.  
  1406.                 if(HandleSearchMessage(Context,&Message))
  1407.                 {
  1408.                     BOOL Ok = Context->Ok;
  1409.  
  1410.                     DeleteSearchContext(Context);
  1411.  
  1412.                     Context = NULL;
  1413.  
  1414.                     if(Ok)
  1415.                     {
  1416.                         if(SearchInfo)
  1417.                             DeleteSearchInfo(SearchInfo);
  1418.  
  1419.                         if(SearchInfo = CreateSearchInfo(SearchBuffer,BufferInfo->SearchForward,BufferInfo->IgnoreCase,BufferInfo->WholeWords))
  1420.                             StartSearch(BufferInfo,SearchInfo,SearchBuffer);
  1421.                     }
  1422.                     else
  1423.                     {
  1424.                         if(SearchInfo)
  1425.                             DeleteSearchInfo(SearchInfo);
  1426.  
  1427.                         SearchInfo = NULL;
  1428.                     }
  1429.                 }
  1430.             }
  1431.             else
  1432.             {
  1433.                 MsgClass        = Message->Class;
  1434.                 MsgCode            = Message->Code;
  1435.                 MsgQualifier    = Message->Qualifier;
  1436.                 MouseX            = Message->MouseX - BufferInfo->Left;
  1437.                 MouseY            = Message->MouseY - BufferInfo->Top;
  1438.                 Seconds            = Message->Seconds;
  1439.                 Micros            = Message->Micros;
  1440.  
  1441.                 WindowJustActivated    = FALSE;
  1442.                 MsgGadgetID            = 0;
  1443.  
  1444.                 switch(MsgClass)
  1445.                 {
  1446.                     case IDCMP_SIZEVERIFY:
  1447.  
  1448.                         BufferMarkerStop(BufferInfo);
  1449.                         break;
  1450.  
  1451.                     case IDCMP_IDCMPUPDATE:
  1452.  
  1453.                         MsgGadgetID = (UWORD)GetTagData(GA_ID,0,(struct TagItem *)Message->IAddress);
  1454.                         break;
  1455.  
  1456.                     case IDCMP_GADGETUP:
  1457.                     case IDCMP_GADGETDOWN:
  1458.  
  1459.                         MsgGadgetID = ((struct Gadget *)Message->IAddress)->GadgetID;
  1460.                         break;
  1461.  
  1462.                     case IDCMP_RAWKEY:
  1463.  
  1464.                         FullChar = ConvertTheKey(NULL,0,MsgCode,MsgQualifier,*(ULONG *)Message->IAddress);
  1465.  
  1466.                         if(!(MsgQualifier & IEQUALIFIER_NUMERICPAD))
  1467.                             Char = FullChar;
  1468.                         else
  1469.                             Char = ConvertTheKey(NULL,0,MsgCode,MsgQualifier & ~(CONTROL_KEY | ALT_KEY | SHIFT_KEY),*(ULONG *)Message->IAddress);
  1470.  
  1471.                         break;
  1472.  
  1473.                     case IDCMP_ACTIVEWINDOW:
  1474.                     case IDCMP_MOUSEBUTTONS:
  1475.  
  1476.                         WindowJustActivated = (BOOL)(Seconds == LastSeconds && Micros == LastMicros);
  1477.                         break;
  1478.                 }
  1479.  
  1480.                 LastSeconds    = Seconds;
  1481.                 LastMicros    = Micros;
  1482.  
  1483.                 ReplyMsg((struct Message *)Message);
  1484.             }
  1485.  
  1486.             if(MsgClass == IDCMP_INACTIVEWINDOW)
  1487.                 BufferMarkerInterrupt(BufferInfo);
  1488.  
  1489.             if(MsgClass == IDCMP_IDCMPUPDATE)
  1490.             {
  1491.                 switch(MsgGadgetID)
  1492.                 {
  1493.                     case GAD_UP:
  1494.  
  1495.                         DisplayDirty    = TRUE;
  1496.                         NewTopLine        = BufferInfo->TopLine - 1;
  1497.  
  1498.                         break;
  1499.  
  1500.                     case GAD_DOWN:
  1501.  
  1502.                         DisplayDirty    = TRUE;
  1503.                         NewTopLine        = BufferInfo->TopLine + 1;
  1504.  
  1505.                         break;
  1506.                 }
  1507.             }
  1508.  
  1509.             if(MsgClass == IDCMP_MOUSEMOVE || MsgClass == IDCMP_INTUITICKS)
  1510.                 BufferMarkerMoveMouse(BufferInfo);
  1511.  
  1512.             if(MsgClass == IDCMP_MOUSEMOVE || ((MsgClass == IDCMP_GADGETDOWN || MsgClass == IDCMP_GADGETUP) && MsgGadgetID == GAD_SCROLLER))
  1513.             {
  1514.                 GetAttr(PGA_Top,BufferInfo->Scroller,(ULONG *)&NewTopLine);
  1515.  
  1516.                 DisplayDirty        = TRUE;
  1517.                 DoNotUpdateScroller    = TRUE;
  1518.             }
  1519.  
  1520.             if(MsgClass == IDCMP_MOUSEBUTTONS)
  1521.             {
  1522.                 if(!WindowJustActivated || MsgCode != SELECTDOWN)
  1523.                 {
  1524.                     switch(MsgCode)
  1525.                     {
  1526.                         case SELECTUP:
  1527.  
  1528.                             BufferMarkerInterrupt(BufferInfo);
  1529.                             break;
  1530.  
  1531.                         case SELECTDOWN:
  1532.  
  1533.                             if(TestingDoubleClick)
  1534.                             {
  1535.                                 ULONG CurrentSeconds,CurrentMicros;
  1536.  
  1537.                                 TestingDoubleClick = FALSE;
  1538.  
  1539.                                 CurrentTime(&CurrentSeconds,&CurrentMicros);
  1540.  
  1541.                                 if(DoubleClick(ClickSeconds,ClickMicros,CurrentSeconds,CurrentMicros))
  1542.                                 {
  1543.                                     BufferMarkWord(BufferInfo);
  1544.  
  1545.                                     break;
  1546.                                 }
  1547.                             }
  1548.                             else
  1549.                             {
  1550.                                 TestingDoubleClick = TRUE;
  1551.  
  1552.                                 CurrentTime(&ClickSeconds,&ClickMicros);
  1553.                             }
  1554.  
  1555.                             BufferMarkerStart(BufferInfo,MsgQualifier);
  1556.                             break;
  1557.                     }
  1558.                 }
  1559.             }
  1560.  
  1561.             if(MsgClass == IDCMP_RAWKEY)
  1562.             {
  1563.                 switch(MsgCode)
  1564.                 {
  1565.                     case HELP_CODE:
  1566.  
  1567.                         GuideDisplay(CONTEXT_TEXTBUFFER);
  1568.                         break;
  1569.  
  1570.                         /* Scroll the buffer up. */
  1571.  
  1572.                     case CURSOR_UP_CODE:
  1573.  
  1574.                         DisplayDirty = TRUE;
  1575.  
  1576.                         if(MsgQualifier & (CONTROL_KEY | ALT_KEY))
  1577.                         {
  1578.                             NewTopLine = 0;
  1579.  
  1580.                             break;
  1581.                         }
  1582.  
  1583.                         if(MsgQualifier & SHIFT_KEY)
  1584.                         {
  1585.                             NewTopLine = BufferInfo->TopLine - (BufferInfo->NumBufferLines - 1);
  1586.  
  1587.                             break;
  1588.                         }
  1589.  
  1590.                         NewTopLine = BufferInfo->TopLine - 1;
  1591.                         break;
  1592.  
  1593.                         /* Scroll the buffer down. */
  1594.  
  1595.                     case CURSOR_DOWN_CODE:
  1596.  
  1597.                         DisplayDirty = TRUE;
  1598.  
  1599.                         if(MsgQualifier & (CONTROL_KEY | ALT_KEY))
  1600.                         {
  1601.                             NewTopLine = Lines - BufferInfo->NumBufferLines;
  1602.  
  1603.                             break;
  1604.                         }
  1605.  
  1606.                         if(MsgQualifier & SHIFT_KEY)
  1607.                         {
  1608.                             NewTopLine = BufferInfo->TopLine + (BufferInfo->NumBufferLines - 1);
  1609.  
  1610.                             break;
  1611.                         }
  1612.  
  1613.                         NewTopLine = BufferInfo->TopLine + 1;
  1614.                         break;
  1615.  
  1616.                     default:
  1617.  
  1618.                             /* Use the numeric keypad keys to
  1619.                              * move through the buffer.
  1620.                              */
  1621.  
  1622.                         if(!(MsgQualifier & IEQUALIFIER_NUMERICPAD))
  1623.                             Char = FullChar;
  1624.                         else
  1625.                         {
  1626.                             switch(Char - '0')
  1627.                             {
  1628.                                     /* Jump to bottom. */
  1629.  
  1630.                                 case 1:
  1631.  
  1632.                                     DisplayDirty    = TRUE;
  1633.                                     NewTopLine        = Lines - BufferInfo->NumBufferLines;
  1634.  
  1635.                                     break;
  1636.  
  1637.                                     /* Move one line down. */
  1638.  
  1639.                                 case 2:
  1640.  
  1641.                                     DisplayDirty    = TRUE;
  1642.                                     NewTopLine        = BufferInfo->TopLine + 1;
  1643.  
  1644.                                     break;
  1645.  
  1646.                                     /* Move one page down. */
  1647.  
  1648.                                 case 3:
  1649.  
  1650.                                     DisplayDirty    = TRUE;
  1651.                                     NewTopLine        = BufferInfo->TopLine + (BufferInfo->NumBufferLines - 1);
  1652.  
  1653.                                     break;
  1654.  
  1655.                                     /* Jump to top. */
  1656.  
  1657.                                 case 7:
  1658.  
  1659.                                     DisplayDirty    = TRUE;
  1660.                                     NewTopLine        = 0;
  1661.  
  1662.                                     break;
  1663.  
  1664.                                     /* Move one line up. */
  1665.  
  1666.                                 case 8:
  1667.  
  1668.                                     DisplayDirty    = TRUE;
  1669.                                     NewTopLine        = BufferInfo->TopLine - 1;
  1670.  
  1671.                                     break;
  1672.  
  1673.                                     /* Move one page up. */
  1674.  
  1675.                                 case 9:
  1676.  
  1677.                                     DisplayDirty    = TRUE;
  1678.                                     NewTopLine        = BufferInfo->TopLine - (BufferInfo->NumBufferLines - 1);
  1679.  
  1680.                                     break;
  1681.                             }
  1682.  
  1683.                             if(Char >= '0' && Char <= '9')
  1684.                                 Char = 0;
  1685.                             else
  1686.                                 Char = FullChar;
  1687.                         }
  1688.  
  1689.                         if(Char > 0 && BufferInfo->Parent)
  1690.                         {
  1691.                             if(Config->SerialConfig->StripBit8)
  1692.                                 Char &= 0x7F;
  1693.  
  1694.                             if(Get_xOFF())
  1695.                             {
  1696.                                 if(Char == XON)
  1697.                                     Clear_xOFF();
  1698.                             }
  1699.                             else
  1700.                             {
  1701.                                 STRPTR String;
  1702.                                 LONG Length;
  1703.  
  1704.                                 String = &Char;
  1705.                                 Length = 1;
  1706.  
  1707.                                     /* Convert chars as appropriate */
  1708.  
  1709.                                 switch(Char)
  1710.                                 {
  1711.                                     case '\n':
  1712.  
  1713.                                         switch(Config->TerminalConfig->SendLF)
  1714.                                         {
  1715.                                             case EOL_LF:
  1716.  
  1717.                                                 break;
  1718.  
  1719.                                             case EOL_LFCR:
  1720.  
  1721.                                                 String = "\n\r";
  1722.                                                 Length = 2;
  1723.                                                 break;
  1724.  
  1725.                                             case EOL_CRLF:
  1726.  
  1727.                                                 String = "\r\n";
  1728.                                                 Length = 2;
  1729.                                                 break;
  1730.  
  1731.                                             case EOL_CR:
  1732.  
  1733.                                                 String = "\r";
  1734.                                                 break;
  1735.                                         }
  1736.  
  1737.                                         break;
  1738.  
  1739.                                     case '\r':
  1740.  
  1741.                                         switch(Config->TerminalConfig->SendCR)
  1742.                                         {
  1743.                                             case EOL_CR:
  1744.  
  1745.                                                 break;
  1746.  
  1747.                                             case EOL_LFCR:
  1748.  
  1749.                                                 String = "\n\r";
  1750.                                                 Length = 2;
  1751.                                                 break;
  1752.  
  1753.                                             case EOL_CRLF:
  1754.  
  1755.                                                 String = "\r\n";
  1756.                                                 Length = 2;
  1757.                                                 break;
  1758.  
  1759.                                             case EOL_LF:
  1760.  
  1761.                                                 String = "\n";
  1762.                                                 break;
  1763.                                         }
  1764.  
  1765.                                         break;
  1766.  
  1767.                                         /* Restart in/output. */
  1768.  
  1769.                                     case XON:
  1770.  
  1771.                                         if(Config->SerialConfig->xONxOFF)
  1772.                                             Clear_xOFF();
  1773.  
  1774.                                         if(!Config->SerialConfig->PassThrough)
  1775.                                             Length = 0;
  1776.  
  1777.                                         break;
  1778.  
  1779.                                         /* Stop in/output. */
  1780.  
  1781.                                     case XOF:
  1782.  
  1783.                                         if(Config->SerialConfig->xONxOFF)
  1784.                                             Set_xOFF();
  1785.  
  1786.                                         if(!Config->SerialConfig->PassThrough)
  1787.                                             Length = 0;
  1788.  
  1789.                                         break;
  1790.  
  1791.                                         /* Convert special Amiga characters into
  1792.                                          * alien IBM dialect.
  1793.                                          */
  1794.  
  1795.                                     default:
  1796.  
  1797.                                         if(Config->TerminalConfig->FontMode == FONT_IBM)
  1798.                                         {
  1799.                                             if(IBMConversion[Char])
  1800.                                                 Char = IBMConversion[Char];
  1801.                                             else
  1802.                                                 Length = 0;
  1803.                                         }
  1804.  
  1805.                                         break;
  1806.                                 }
  1807.  
  1808.                                 if(Length > 0)
  1809.                                     BufferSerWrite(BufferInfo,String,Length);
  1810.                             }
  1811.                         }
  1812.  
  1813.                         break;
  1814.                 }
  1815.             }
  1816.  
  1817.             if(MsgClass == IDCMP_MENUHELP)
  1818.                 GuideDisplay(CONTEXT_BUFFER_MENU);
  1819.  
  1820.             if(MsgClass == IDCMP_CLOSEWINDOW)
  1821.                 BufferInfo->BufferTerminated = TRUE;
  1822.  
  1823.             if(MsgClass == IDCMP_NEWSIZE)
  1824.             {
  1825.                 LONG Width,Height;
  1826.  
  1827.                 BufferInfo->Width                = BufferInfo->Window->Width        - (BufferInfo->Window->BorderLeft    + BufferInfo->Window->BorderRight);
  1828.                 BufferInfo->Height                = BufferInfo->Window->Height    - (BufferInfo->Window->BorderTop    + BufferInfo->Window->BorderBottom);
  1829.  
  1830.                 Width                            = BufferInfo->Width        - (BufferInfo->Width    % BufferInfo->LocalTextFontWidth);
  1831.                 Height                            = BufferInfo->Height    - (BufferInfo->Height    % BufferInfo->LocalTextFontHeight);
  1832.  
  1833.                 BufferInfo->NumBufferColumns    = Width / BufferInfo->LocalTextFontWidth;
  1834.                 BufferInfo->NumBufferLines        = Height / BufferInfo->LocalTextFontHeight;
  1835.  
  1836.                 if(Width < BufferInfo->Width)
  1837.                     BufferClear(BufferInfo,Width,0,BufferInfo->Width - 1,BufferInfo->Height - 1);
  1838.  
  1839.                 if(Height < BufferInfo->Height)
  1840.                     BufferClear(BufferInfo,0,Height,BufferInfo->Width - 1,BufferInfo->Height - 1);
  1841.  
  1842.                 BufferInfo->Width    = Width;
  1843.                 BufferInfo->Height    = Height;
  1844.  
  1845.                 BufferInfo->LastTopLine = -1;
  1846.                 BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine);
  1847.  
  1848.                 SetGadgetAttrs((struct Gadget *)BufferInfo->Scroller,BufferInfo->Window,NULL,
  1849.                     PGA_Total,        Lines,
  1850.                     PGA_Top,        BufferInfo->TopLine,
  1851.                     PGA_Visible,    BufferInfo->DisplayedLines,
  1852.                 TAG_DONE);
  1853.  
  1854.                 UpdatePercent = TRUE;
  1855.             }
  1856.  
  1857.             if(MsgClass == IDCMP_MENUPICK)
  1858.             {
  1859.                 struct MenuItem    *MenuItem;
  1860.                 struct DataMsg     Msg;
  1861.  
  1862.                 while(MsgCode != MENUNULL)
  1863.                 {
  1864.                     if(!(MenuItem = ItemAddress(BufferInfo->BufferMenuStrip,MsgCode)))
  1865.                         break;
  1866.                     else
  1867.                     {
  1868.                         switch((ULONG)GTMENUITEM_USERDATA(MenuItem))
  1869.                         {
  1870.                             case MEN_COPYCLIP:
  1871.  
  1872.                                 BufferMarkerTransfer(BufferInfo,MsgQualifier);
  1873.                                 break;
  1874.  
  1875.                             case MEN_CLEARCLIP:
  1876.  
  1877.                                 BufferMarkerStop(BufferInfo);
  1878.                                 break;
  1879.  
  1880.                             case MEN_SELECT_ALL_CLIP:
  1881.  
  1882.                                 BufferMarkerSelectAll(BufferInfo);
  1883.                                 break;
  1884.  
  1885.                             case MEN_PASTECLIP:
  1886.  
  1887.                                 InitMsgItem(&Msg,(DESTRUCTOR)BufferDestructor);
  1888.  
  1889.                                 Msg.Type    = DATAMSGTYPE_WRITECLIP;
  1890.                                 Msg.Size    = Config->ClipConfig->ClipboardUnit;
  1891.                                 Msg.Client    = FindTask(NULL);
  1892.                                 Msg.Mask    = 1UL << BufferInfo->BufferSignal;
  1893.  
  1894.                                 Forbid();
  1895.  
  1896.                                 ClrSignal(Msg.Mask);
  1897.  
  1898.                                 PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1899.  
  1900.                                 Wait(Msg.Mask);
  1901.  
  1902.                                 Permit();
  1903.                                 break;
  1904.  
  1905.                             case MEN_SEARCH:
  1906.  
  1907.                                 if(Context)
  1908.                                     LT_ShowWindow(Context->SearchHandle,TRUE);
  1909.                                 else
  1910.                                     Context = CreateSearchContext(BufferInfo->Window,SearchBuffer,&HistoryHook,(struct List *)&TextBufferHistory,&BufferInfo->SearchForward,&BufferInfo->IgnoreCase,&BufferInfo->WholeWords);
  1911.  
  1912.                                 UpdatePercent = TRUE;
  1913.  
  1914.                                 break;
  1915.  
  1916.                             case MEN_REPEAT:
  1917.  
  1918.                                 if(Context)
  1919.                                     LT_ShowWindow(Context->SearchHandle,TRUE);
  1920.                                 else
  1921.                                 {
  1922.                                     if(SearchInfo)
  1923.                                         StartSearch(BufferInfo,SearchInfo,SearchBuffer);
  1924.                                     else
  1925.                                         Context = CreateSearchContext(BufferInfo->Window,SearchBuffer,&HistoryHook,(struct List *)&TextBufferHistory,&BufferInfo->SearchForward,&BufferInfo->IgnoreCase,&BufferInfo->WholeWords);
  1926.                                 }
  1927.  
  1928.                                 UpdatePercent = TRUE;
  1929.  
  1930.                                 break;
  1931.  
  1932.                             case MEN_GOTO:
  1933.  
  1934.                                 if(Window)
  1935.                                     BumpWindow(Window);
  1936.  
  1937.                                 break;
  1938.  
  1939.                             case MEN_QUITBUF:
  1940.  
  1941.                                 BufferInfo->BufferTerminated = TRUE;
  1942.                                 break;
  1943.  
  1944.                             case MEN_CLEARBUF_CONTENTS:
  1945.  
  1946.                                 if(Lines)
  1947.                                 {
  1948.                                     struct DataMsg *Msg;
  1949.  
  1950.                                     if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg)))
  1951.                                     {
  1952.                                         Msg->Type = DATAMSGTYPE_CLEARBUFFER;
  1953.  
  1954.                                         UpdatePercent = TRUE;
  1955.  
  1956.                                         LT_LockWindow(BufferInfo->Window);
  1957.  
  1958.                                         if(MsgQualifier & SHIFT_KEY)
  1959.                                         {
  1960.                                             PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
  1961.                                             Msg = NULL;
  1962.                                         }
  1963.                                         else
  1964.                                         {
  1965.                                             if(Config->MiscConfig->ProtectiveMode)
  1966.                                             {
  1967.                                                 if(!ShowRequest(BufferInfo->Window,LocaleString(MSG_TERMBUFFER_BUFFER_STILL_HOLDS_LINES_TXT),LocaleString(MSG_GLOBAL_YES_NO_TXT),Lines))
  1968.                                                 {
  1969.                                                     LT_UnlockWindow(BufferInfo->Window);
  1970.  
  1971.                                                     break;
  1972.                                                 }
  1973.                                             }
  1974.  
  1975.                                             PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
  1976.                                             Msg = NULL;
  1977.                                         }
  1978.  
  1979.                                         DeleteMsgItem((struct MsgItem *)Msg);
  1980.                                     }
  1981.  
  1982.                                     LT_UnlockWindow(BufferInfo->Window);
  1983.  
  1984.                                     FlushMsg(BufferInfo->Window);
  1985.                                 }
  1986.  
  1987.                                 break;
  1988.                         }
  1989.  
  1990.                         MsgCode = MenuItem->NextSelect;
  1991.                     }
  1992.                 }
  1993.             }
  1994.  
  1995.             if(DisplayDirty)
  1996.             {
  1997.                 DisplayDirty = FALSE;
  1998.  
  1999.                 if(NewTopLine < 0)
  2000.                     NewTopLine = 0;
  2001.                 else if (NewTopLine + BufferInfo->NumBufferLines >= Lines)
  2002.                     NewTopLine = Lines - BufferInfo->NumBufferLines;
  2003.  
  2004.                 if(NewTopLine >= 0 && NewTopLine != BufferInfo->TopLine)
  2005.                 {
  2006.                     BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,NewTopLine);
  2007.  
  2008.                     BufferInfo->TopLine = NewTopLine;
  2009.  
  2010.                     if(DoNotUpdateScroller)
  2011.                         DoNotUpdateScroller = FALSE;
  2012.                     else
  2013.                     {
  2014.                         SetGadgetAttrs((struct Gadget *)BufferInfo->Scroller,BufferInfo->Window,NULL,
  2015.                             PGA_Top,BufferInfo->TopLine,
  2016.                         TAG_DONE);
  2017.                     }
  2018.  
  2019.                     UpdatePercent = TRUE;
  2020.                 }
  2021.             }
  2022.         }
  2023.     }
  2024.  
  2025.     if(Context)
  2026.         DeleteSearchContext(Context);
  2027.  
  2028.     if(SearchInfo)
  2029.         DeleteSearchInfo(SearchInfo);
  2030.  
  2031.         /* Put the stuff back */
  2032.  
  2033.     *BufferInfo->pTopLine        = BufferInfo->TopLine;
  2034.     *BufferInfo->pSearchForward    = BufferInfo->SearchForward;
  2035.     *BufferInfo->pIgnoreCase    = BufferInfo->IgnoreCase;
  2036.     *BufferInfo->pWholeWords    = BufferInfo->WholeWords;
  2037.  
  2038.     return(RingBack);
  2039. }
  2040.  
  2041. STATIC VOID
  2042. DeleteBufferInfo(TextBufferInfo *BufferInfo)
  2043. {
  2044.     if(BufferInfo)
  2045.     {
  2046.         FreeVecPooled(BufferInfo->BufferLineOffsets);
  2047.  
  2048.         if(BufferInfo->Window)
  2049.         {
  2050.             ClearMenuStrip(BufferInfo->Window);
  2051.  
  2052.             LT_DeleteWindowLock(BufferInfo->Window);
  2053.  
  2054.             CloseWindow(BufferInfo->Window);
  2055.         }
  2056.  
  2057.         FreeVecPooled(BufferInfo->Marker);
  2058.  
  2059.         DeleteScroller(BufferInfo);
  2060.  
  2061.         DisposeObject(BufferInfo->BufferAmigaGlyph);
  2062.         DisposeObject(BufferInfo->BufferCheckGlyph);
  2063.  
  2064.         FreeScreenDrawInfo(BufferInfo->Screen,BufferInfo->BufferDrawInfo);
  2065.  
  2066.         LT_DisposeMenu(BufferInfo->BufferMenuStrip);
  2067.  
  2068.         if(BufferInfo->Screen && !BufferInfo->Parent)
  2069.             CloseScreen(BufferInfo->Screen);
  2070.  
  2071.         if(BufferInfo->LocalFont)
  2072.             CloseFont(BufferInfo->LocalFont);
  2073.  
  2074.         if(BufferInfo->BufferSignal != -1)
  2075.             FreeSignal(BufferInfo->BufferSignal);
  2076.  
  2077.         DeleteMsgQueue(BufferInfo->Queue);
  2078.  
  2079.         FreeVecPooled(BufferInfo);
  2080.     }
  2081. }
  2082.  
  2083. STATIC TextBufferInfo *
  2084. CreateBufferInfo(struct Screen *Parent,BOOL *pSearchForward,BOOL *pIgnoreCase,BOOL *pWholeWords,LONG *pTopLine)
  2085. {
  2086.     TextBufferInfo *BufferInfo;
  2087.  
  2088.     if(BufferInfo = (TextBufferInfo *)AllocVecPooled(sizeof(TextBufferInfo),MEMF_ANY | MEMF_CLEAR))
  2089.     {
  2090.         LONG                         Width,Height;
  2091.         ULONG                         DisplayMode;
  2092.  
  2093.         struct Rectangle             DisplayClip;
  2094.         struct DimensionInfo         DimensionInfo;
  2095.  
  2096.         BufferInfo->pSearchForward    = pSearchForward;
  2097.         BufferInfo->pIgnoreCase        = pIgnoreCase;
  2098.         BufferInfo->pWholeWords        = pWholeWords;
  2099.         BufferInfo->pTopLine        = pTopLine;
  2100.  
  2101.         BufferInfo->TopLine            = *pTopLine;
  2102.         BufferInfo->LastTopLine        = -1;
  2103.  
  2104.         BufferInfo->SearchForward    = *pSearchForward;
  2105.         BufferInfo->IgnoreCase        = *pIgnoreCase;
  2106.         BufferInfo->WholeWords        = *pWholeWords;
  2107.  
  2108.         BufferInfo->OldColumn        = -1;
  2109.         BufferInfo->OldLine            = -1;
  2110.         BufferInfo->OldLength        = -1;
  2111.  
  2112.         BufferInfo->Buddy            = (struct Process *)FindTask(NULL);
  2113.  
  2114.         CopyMem(&TextFont,&BufferInfo->LocalTextFont,sizeof(struct TTextAttr));
  2115.  
  2116.         BufferInfo->LocalTextFont.tta_Name    = BufferInfo->LocalTextFontName;
  2117.         BufferInfo->LocalTextFont.tta_YSize    = Config->TerminalConfig->TextFontHeight;
  2118.  
  2119.         strcpy(BufferInfo->LocalTextFontName,Config->TerminalConfig->TextFontName);
  2120.  
  2121.         CopyMem(&UserFont,&BufferInfo->LocalUserFont,sizeof(struct TTextAttr));
  2122.  
  2123.         BufferInfo->LocalUserFont.tta_Name = BufferInfo->LocalUserFontName;
  2124.  
  2125.         strcpy(BufferInfo->LocalUserFontName,UserFont.tta_Name);
  2126.  
  2127.         if(!Config->CaptureConfig->ConvertChars && Config->TerminalConfig->FontMode != FONT_STANDARD)
  2128.         {
  2129.             strcpy(BufferInfo->LocalTextFontName,Config->TerminalConfig->IBMFontName);
  2130.  
  2131.             BufferInfo->LocalTextFont.tta_YSize = Config->TerminalConfig->IBMFontHeight;
  2132.  
  2133.             BufferInfo->NeedClipConversion = TRUE;
  2134.         }
  2135.         else
  2136.             BufferInfo->NeedClipConversion = FALSE;
  2137.  
  2138.         if(BufferInfo->LocalFont = SmartOpenDiskFont((struct TextAttr *)&BufferInfo->LocalTextFont))
  2139.         {
  2140.             BufferInfo->LocalTextFontWidth    = BufferInfo->LocalFont->tf_XSize;
  2141.             BufferInfo->LocalTextFontHeight    = BufferInfo->LocalFont->tf_YSize;
  2142.  
  2143.             DisplayMode = Config->CaptureConfig->BufferScreenMode;
  2144.  
  2145.             if(DisplayMode == INVALID_ID && Window)
  2146.                 DisplayMode = GetVPModeID(&Window->WScreen->ViewPort);
  2147.  
  2148.             if(ModeNotAvailable(DisplayMode))
  2149.                 DisplayMode = Config->ScreenConfig->DisplayMode;
  2150.  
  2151.             if(ModeNotAvailable(DisplayMode))
  2152.             {
  2153.                 struct Screen *PubScreen = LockPubScreen(NULL);
  2154.  
  2155.                 if(PubScreen)
  2156.                 {
  2157.                     DisplayMode = GetVPModeID(&PubScreen->ViewPort);
  2158.  
  2159.                     UnlockPubScreen(NULL,PubScreen);
  2160.                 }
  2161.                 else
  2162.                     DisplayMode = DEFAULT_MONITOR_ID | HIRES_KEY;
  2163.             }
  2164.  
  2165.                 /* Set up the actual width of the screen we want. */
  2166.  
  2167.             Width = Config->CaptureConfig->BufferWidth * BufferInfo->LocalTextFontWidth + BufferInfo->ArrowWidth + 1;
  2168.  
  2169.             if((BufferInfo->BufferSignal = AllocSignal(-1)) != -1)
  2170.             {
  2171.                     /* Get the mode dimension info. */
  2172.  
  2173.                 if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,DisplayMode))
  2174.                 {
  2175.                         /* Determine maximum text overscan width. */
  2176.  
  2177.                     LONG TextWidth = DimensionInfo.TxtOScan.MaxX - DimensionInfo.TxtOScan.MinX + 1;
  2178.  
  2179.                         /* Too small? */
  2180.  
  2181.                     if(Width < DimensionInfo.MinRasterWidth)
  2182.                         Width = DimensionInfo.MinRasterWidth;
  2183.  
  2184.                         /* Far too large? */
  2185.  
  2186.                     if(Width > DimensionInfo.MaxRasterWidth)
  2187.                         Width = DimensionInfo.MaxRasterWidth;
  2188.  
  2189.                         /* A bit too large? */
  2190.  
  2191.                     if(Width > TextWidth)
  2192.                         Width = TextWidth;
  2193.  
  2194.                         /* Inquire the text overscan dimensions. */
  2195.  
  2196.                     if(QueryOverscan(DisplayMode,&DisplayClip,OSCAN_TEXT))
  2197.                     {
  2198.                             /* Centre the buffer screen. */
  2199.  
  2200.                         if(DisplayClip.MaxX - DisplayClip.MinX + 1 > Width)
  2201.                         {
  2202.                             LONG Differ = (DisplayClip.MaxX - DisplayClip.MinX + 1 - Width) / 2;
  2203.  
  2204.                             switch(Config->CaptureConfig->BufferScreenPosition)
  2205.                             {
  2206.                                 case SCREEN_LEFT:
  2207.  
  2208.                                     DisplayClip.MaxX = DisplayClip.MinX + Width;
  2209.                                     break;
  2210.  
  2211.                                 case SCREEN_RIGHT:
  2212.  
  2213.                                     DisplayClip.MinX = DisplayClip.MaxX - Width;
  2214.                                     break;
  2215.  
  2216.                                 case SCREEN_CENTRE:
  2217.  
  2218.                                     DisplayClip.MinX += Differ;
  2219.                                     DisplayClip.MaxX -= Differ;
  2220.  
  2221.                                     break;
  2222.                             }
  2223.                         }
  2224.  
  2225.                             /* Open a two bitplane clone of the main screen. */
  2226.  
  2227.                         if(Parent)
  2228.                         {
  2229.                             BufferInfo->Parent = Parent;
  2230.                             BufferInfo->Screen = Parent;
  2231.  
  2232.                             if(BufferInfo->Queue = CreateMsgQueue(NULL,0))
  2233.                                 BufferInfo->QueueMask = BufferInfo->Queue->SigMask;
  2234.                             else
  2235.                                 BufferInfo->Screen = NULL;
  2236.                         }
  2237.                         else
  2238.                         {
  2239.                             UWORD Pens = (UWORD)~0;
  2240.  
  2241.                             BufferInfo->Screen = OpenScreenTags(NULL,
  2242.                                 SA_Title,        LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),
  2243.                                 SA_Depth,        2,
  2244.                                 SA_Left,        DisplayClip.MinX,
  2245.                                 SA_DClip,        &DisplayClip,
  2246.                                 SA_DisplayID,    DisplayMode,
  2247.                                 SA_Font,        &BufferInfo->LocalUserFont,
  2248.                                 SA_AutoScroll,    TRUE,
  2249.                                 SA_Pens,        &Pens,
  2250.                             TAG_END);
  2251.                         }
  2252.  
  2253.                         if(BufferInfo->Screen)
  2254.                         {
  2255.                             if(BufferInfo->BufferDrawInfo = GetScreenDrawInfo(BufferInfo->Screen))
  2256.                             {
  2257.                                 ULONG *MenuTags;
  2258.  
  2259.                                 CreateMenuGlyphs(BufferInfo->Screen,BufferInfo->BufferDrawInfo,&BufferInfo->BufferAmigaGlyph,&BufferInfo->BufferCheckGlyph);
  2260.  
  2261.                                 if(Parent)
  2262.                                 {
  2263.                                     STATIC ULONG ReviewTags[] =
  2264.                                     {
  2265.                                         LAMN_TitleID,            MSG_TERMREVIEW_PROJECT_MEN,
  2266.                                             LAMN_ItemID,        MSG_TERMREVIEW_SEARCH_MEN,
  2267.                                                 LAMN_UserData,    MEN_SEARCH,
  2268.                                             LAMN_ItemID,        MSG_TERMREVIEW_REPEAT_SEARCH_MEN,
  2269.                                                 LAMN_UserData,    MEN_REPEAT,
  2270.  
  2271.                                             LAMN_ItemText,        (ULONG)NM_BARLABEL,
  2272.  
  2273.                                             LAMN_ItemID,        MSG_TERMREVIEW_CLEAR_BUFFER_MEN,
  2274.                                                 LAMN_UserData,    MEN_CLEARBUF_CONTENTS,
  2275.  
  2276.                                             LAMN_ItemText,        (ULONG)NM_BARLABEL,
  2277.  
  2278.                                             LAMN_ItemID,        MSG_TERMREVIEW_CLOSE_BUFFER_MEN,
  2279.                                                 LAMN_UserData,    MEN_QUITBUF,
  2280.  
  2281.                                             LAMN_ItemID,        MSG_CLOSE_WINDOW_TXT,
  2282.                                                 LAMN_KeyText,    (ULONG)":",
  2283.                                                 LAMN_UserData,    MEN_QUITBUF,
  2284.  
  2285.                                         LAMN_TitleID,            MSG_TERMBUFFER_EDIT_MEN,
  2286.                                             LAMN_ItemID,        MSG_TERMDATA_COPY_MEN,
  2287.                                                 LAMN_UserData,    MEN_COPYCLIP,
  2288.                                             LAMN_ItemID,        MSG_TERMDATA_PASTE_MEN,
  2289.                                                 LAMN_UserData,    MEN_PASTECLIP,
  2290.                                             LAMN_ItemID,        MSG_TERMDATA_CLEAR_MEN,
  2291.                                                 LAMN_UserData,    MEN_CLEARCLIP,
  2292.  
  2293.                                             LAMN_ItemText,        (ULONG)NM_BARLABEL,
  2294.  
  2295.                                             LAMN_ItemID,        MSG_SELECT_ALL_MEN,
  2296.                                                 LAMN_UserData,    MEN_SELECT_ALL_CLIP,
  2297.  
  2298.                                         TAG_DONE
  2299.                                     };
  2300.  
  2301.                                     MenuTags = ReviewTags;
  2302.                                 }
  2303.                                 else
  2304.                                 {
  2305.                                     STATIC ULONG BufferTags[] =
  2306.                                     {
  2307.                                         LAMN_TitleID,            MSG_TERMBUFFER_PROJECT_MEN,
  2308.                                             LAMN_ItemID,        MSG_TERMBUFFER_SEARCH_MEN,
  2309.                                                 LAMN_UserData,    MEN_SEARCH,
  2310.                                             LAMN_ItemID,        MSG_TERMBUFFER_REPEAT_SEARCH_MEN,
  2311.                                                 LAMN_UserData,    MEN_REPEAT,
  2312.  
  2313.                                             LAMN_ItemText,        (ULONG)NM_BARLABEL,
  2314.  
  2315.                                             LAMN_ItemID,        MSG_TERMBUFFER_GO_TO_MAIN_SCREEN_MEN,
  2316.                                                 LAMN_UserData,    MEN_GOTO,
  2317.  
  2318.                                             LAMN_ItemText,        (ULONG)NM_BARLABEL,
  2319.  
  2320.                                             LAMN_ItemID,        MSG_TERMBUFFER_CLEAR_BUFFER_MEN,
  2321.                                                 LAMN_UserData,    MEN_CLEARBUF_CONTENTS,
  2322.  
  2323.                                             LAMN_ItemText,        (ULONG)NM_BARLABEL,
  2324.  
  2325.                                             LAMN_ItemID,        MSG_TERMBUFFER_CLOSE_BUFFER_MEN,
  2326.                                                 LAMN_UserData,    MEN_QUITBUF,
  2327.  
  2328.                                         LAMN_TitleID,            MSG_TERMBUFFER_EDIT_MEN,
  2329.                                             LAMN_ItemID,        MSG_TERMDATA_COPY_MEN,
  2330.                                                 LAMN_UserData,    MEN_COPYCLIP,
  2331.                                             LAMN_ItemID,        MSG_TERMDATA_PASTE_MEN,
  2332.                                                 LAMN_UserData,    MEN_PASTECLIP,
  2333.                                             LAMN_ItemID,        MSG_TERMDATA_CLEAR_MEN,
  2334.                                                 LAMN_UserData,    MEN_CLEARCLIP,
  2335.  
  2336.                                             LAMN_ItemText,        (ULONG)NM_BARLABEL,
  2337.  
  2338.                                             LAMN_ItemID,        MSG_SELECT_ALL_MEN,
  2339.                                                 LAMN_UserData,    MEN_SELECT_ALL_CLIP,
  2340.  
  2341.                                         TAG_DONE
  2342.                                     };
  2343.  
  2344.                                     MenuTags = BufferTags;
  2345.                                 }
  2346.  
  2347.                                 if(BufferInfo->BufferMenuStrip = LT_NewMenuTags(
  2348.                                     LAHN_LocaleHook,        &LocaleHook,
  2349.                                     LAMN_Screen,            BufferInfo->Screen,
  2350.                                     LAMN_TextAttr,            &BufferInfo->LocalUserFont,
  2351.                                     LAMN_AmigaGlyph,        BufferInfo->BufferAmigaGlyph,
  2352.                                     LAMN_CheckmarkGlyph,    BufferInfo->BufferCheckGlyph,
  2353.                                 TAG_MORE,MenuTags))
  2354.                                 {
  2355.                                     UWORD *Pens = BufferInfo->BufferDrawInfo->dri_Pens;
  2356.  
  2357.                                     BufferInfo->TextFrontPen    = Pens[TEXTPEN];
  2358.                                     BufferInfo->TextBackPen        = Pens[BACKGROUNDPEN];
  2359.  
  2360.                                     BufferInfo->MaxPen = MAX(BufferInfo->TextFrontPen,BufferInfo->TextBackPen);
  2361.  
  2362.                                     Height = BufferInfo->Screen->Height - (BufferInfo->Screen->BarHeight + 2);
  2363.  
  2364.                                     if(CreateScroller(BufferInfo,Height))
  2365.                                     {
  2366.                                         LONG Left,Top;
  2367.  
  2368.                                         if(Parent)
  2369.                                         {
  2370.                                             Left    = Window->LeftEdge;
  2371.                                             Top        = Window->TopEdge + Window->BorderTop;
  2372.                                             Width    = Window->Width;
  2373.                                             Height    = Window->Height - Window->BorderTop;
  2374.  
  2375.                                             GetWindowInfo(WINDOW_REVIEW,&Left,&Top,&Width,&Height,Width,Height);
  2376.                                         }
  2377.                                         else
  2378.                                         {
  2379.                                             Left    = 0;
  2380.                                             Top        = BufferInfo->Screen->BarHeight + 2;
  2381.                                             Width    = BufferInfo->Screen->Width;
  2382.                                             Height    = BufferInfo->Screen->Height - Top;
  2383.                                         }
  2384.  
  2385.                                         if(BufferInfo->Window = OpenWindowTags(NULL,
  2386.                                             WA_Left,            Left,
  2387.                                             WA_Top,                Top,
  2388.                                             WA_Width,            Width,
  2389.                                             WA_Height,            Height,
  2390.                                             WA_Backdrop,        Parent == NULL,
  2391.                                             WA_Borderless,        Parent == NULL,
  2392.                                             WA_DepthGadget,        Parent != NULL,
  2393.                                             WA_DragBar,            Parent != NULL,
  2394.                                             WA_CloseGadget,        Parent != NULL,
  2395.                                             WA_SizeGadget,        Parent != NULL,
  2396.                                             WA_NoCareRefresh,    TRUE,
  2397.                                             WA_NewLookMenus,    TRUE,
  2398.                                             WA_IDCMP,            IDCMP_IDCMPUPDATE | IDCMP_RAWKEY | IDCMP_INACTIVEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MOUSEBUTTONS | IDCMP_MENUPICK | IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE | IDCMP_MENUHELP | IDCMP_SIZEVERIFY | IDCMP_NEWSIZE | IDCMP_CLOSEWINDOW,
  2399.                                             WA_MenuHelp,        TRUE,
  2400.                                             WA_Gadgets,            BufferInfo->Scroller,
  2401.                                             WA_CustomScreen,    BufferInfo->Screen,
  2402.                                             WA_Activate,        TRUE,
  2403.                                             BackfillTag,        Parent ? &BackfillHook : NULL,
  2404.  
  2405.                                             BufferInfo->BufferAmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, BufferInfo->BufferAmigaGlyph,
  2406.                                             BufferInfo->BufferCheckGlyph ? WA_Checkmark : TAG_IGNORE, BufferInfo->BufferCheckGlyph,
  2407.                                         TAG_DONE))
  2408.                                         {
  2409.                                             LONG MaxLines,MaxColumns;
  2410.  
  2411.                                             SetMenuStrip(BufferInfo->Window,BufferInfo->BufferMenuStrip);
  2412.  
  2413.                                             OffMenu(BufferInfo->Window,FULLMENUNUM(1,0,NOSUB));
  2414.                                             OffMenu(BufferInfo->Window,FULLMENUNUM(1,2,NOSUB));
  2415.  
  2416.                                             if(!Parent)
  2417.                                                 OffMenu(BufferInfo->Window,FULLMENUNUM(1,1,NOSUB));
  2418.  
  2419.                                             BufferInfo->Left    = BufferInfo->Window->BorderLeft;
  2420.                                             BufferInfo->Top        = BufferInfo->Window->BorderTop;
  2421.                                             BufferInfo->Width    = BufferInfo->Window->Width        - (BufferInfo->Window->BorderLeft    + BufferInfo->Window->BorderRight);
  2422.                                             BufferInfo->Height    = BufferInfo->Window->Height    - (BufferInfo->Window->BorderTop    + BufferInfo->Window->BorderBottom);
  2423.  
  2424.                                             if(!Parent)
  2425.                                                 BufferInfo->Width -= BufferInfo->ArrowWidth;
  2426.  
  2427.                                             BufferInfo->Width    -= BufferInfo->Width    % BufferInfo->LocalTextFontWidth;
  2428.                                             BufferInfo->Height    -= BufferInfo->Height    % BufferInfo->LocalTextFontHeight;
  2429.  
  2430.                                             if(Parent)
  2431.                                                 WindowLimits(BufferInfo->Window,BufferInfo->Window->BorderLeft + 20 * BufferInfo->LocalTextFontWidth + BufferInfo->Window->BorderRight,BufferInfo->Window->BorderTop + BufferInfo->LocalTextFontHeight + BufferInfo->Window->BorderBottom,BufferInfo->Screen->Width,BufferInfo->Screen->Height);
  2432.  
  2433.                                             MaxColumns    = BufferInfo->Window->WScreen->Width / BufferInfo->LocalTextFontWidth + 1;
  2434.                                             MaxLines    = BufferInfo->Window->WScreen->Height / BufferInfo->LocalTextFontHeight + 1;
  2435.  
  2436.                                             if(BufferInfo->BufferLineOffsets = (UWORD *)AllocVecPooled(sizeof(UWORD) * (MaxLines + MaxColumns),MEMF_ANY | MEMF_CLEAR))
  2437.                                             {
  2438.                                                 LONG Index;
  2439.                                                 LONG i;
  2440.  
  2441.                                                 BufferInfo->BufferColumnOffsets    = &BufferInfo->BufferLineOffsets[MaxLines];
  2442.  
  2443.                                                 for(i = Index = 0 ; i < MaxLines ; i++)
  2444.                                                 {
  2445.                                                     BufferInfo->BufferLineOffsets[i] = Index;
  2446.  
  2447.                                                     Index += BufferInfo->LocalTextFontHeight;
  2448.                                                 }
  2449.  
  2450.                                                 for(i = Index = 0 ; i < MaxColumns ; i++)
  2451.                                                 {
  2452.                                                     BufferInfo->BufferColumnOffsets[i] = Index;
  2453.  
  2454.                                                     Index += BufferInfo->LocalTextFontWidth;
  2455.                                                 }
  2456.  
  2457.                                                     /* Determine maximum dimensions of
  2458.                                                      * the buffer screen (in rows and
  2459.                                                      * columns).
  2460.                                                      */
  2461.  
  2462.                                                 if(Parent)
  2463.                                                     BufferInfo->NumBufferColumns = BufferInfo->Width / BufferInfo->LocalTextFontWidth;
  2464.                                                 else
  2465.                                                     BufferInfo->NumBufferColumns = (BufferInfo->Window->Width - (BufferInfo->ArrowWidth + 1)) / BufferInfo->LocalTextFontWidth;
  2466.  
  2467.                                                 BufferInfo->NumBufferLines = BufferInfo->Height / BufferInfo->LocalTextFontHeight;
  2468.  
  2469.                                                 if(BufferInfo->TopLine == -1 || !Config->CaptureConfig->RememberBufferScreen)
  2470.                                                 {
  2471.                                                     switch(Config->CaptureConfig->OpenBufferScreen)
  2472.                                                     {
  2473.                                                         case BUFFER_TOP:
  2474.  
  2475.                                                             BufferInfo->TopLine = 0;
  2476.                                                             break;
  2477.  
  2478.                                                         case BUFFER_END:
  2479.  
  2480.                                                             if((BufferInfo->TopLine = Lines - BufferInfo->NumBufferLines) < 0)
  2481.                                                                 BufferInfo->TopLine = 0;
  2482.  
  2483.                                                             break;
  2484.  
  2485.                                                         default:
  2486.  
  2487.                                                             BufferInfo->TopLine = 0;
  2488.                                                             break;
  2489.                                                     }
  2490.                                                 }
  2491.  
  2492.                                                 if(BufferInfo->TopLine > Lines - BufferInfo->NumBufferLines || BufferInfo->TopLine < 0)
  2493.                                                     BufferInfo->TopLine = 0;
  2494.  
  2495.                                                 BufferInfo->RPort = BufferInfo->Window->RPort;
  2496.  
  2497.                                                 SetFont(BufferInfo->RPort,BufferInfo->LocalFont);
  2498.  
  2499.                                                     /* Bring the screen to the front. */
  2500.  
  2501.                                                 BumpWindow(BufferInfo->Window);
  2502.  
  2503.                                                     /* Set the drawing pens for the window. */
  2504.  
  2505.                                                 if(Kick30)
  2506.                                                 {
  2507.                                                         /* Don't slow down display updates when using an
  2508.                                                          * interleaved screen.
  2509.                                                          */
  2510.  
  2511.                                                     if(!(GetBitMapAttr(BufferInfo->RPort->BitMap,BMA_FLAGS) & BMF_INTERLEAVED))
  2512.                                                         SetMaxPen(BufferInfo->RPort,BufferInfo->MaxPen);
  2513.                                                 }
  2514.  
  2515.                                                 SetPens(BufferInfo->RPort,BufferInfo->TextFrontPen,BufferInfo->TextBackPen,JAM2);
  2516.  
  2517.                                                     /* Initial creation of the buffer display. */
  2518.  
  2519.                                                 BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine);
  2520.  
  2521.                                                 SetGadgetAttrs((struct Gadget *)BufferInfo->Scroller,BufferInfo->Window,NULL,
  2522.                                                     PGA_Top,        BufferInfo->TopLine,
  2523.                                                     PGA_Total,        Lines,
  2524.                                                     PGA_Visible,    BufferInfo->NumBufferLines,
  2525.                                                 TAG_DONE);
  2526.  
  2527.                                                 if(!Parent)
  2528.                                                 {
  2529.                                                     struct RastPort *RPort = BufferInfo->Screen->BarLayer->rp;
  2530.  
  2531.                                                     BufferInfo->TitleOffset = TextLength(RPort,LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),strlen(LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT))) + TextLength(RPort,"  ",1) + 4;
  2532.                                                 }
  2533.  
  2534.                                                 return(BufferInfo);
  2535.                                             }
  2536.                                         }
  2537.                                     }
  2538.                                 }
  2539.                             }
  2540.                         }
  2541.                     }
  2542.                 }
  2543.             }
  2544.         }
  2545.     }
  2546.  
  2547.     DeleteBufferInfo(BufferInfo);
  2548.  
  2549.     return(NULL);
  2550. }
  2551.  
  2552.     /* BufferServer():
  2553.      *
  2554.      *    Asynchronous task to display the data stored in the
  2555.      *    scrollback display buffer.
  2556.      */
  2557.  
  2558. STATIC VOID SAVE_DS
  2559. BufferServer()
  2560. {
  2561.     STATIC BOOL        SearchForward    = TRUE,
  2562.                     IgnoreCase        = TRUE,
  2563.                     WholeWords        = FALSE;
  2564.     STATIC LONG        TopLine            = -1;
  2565.  
  2566.     TextBufferInfo    *BufferInfo;
  2567.     struct Task        *Father,*Me;
  2568.     BOOL             RingBack = TRUE;
  2569.  
  2570.         /* Wake this guy up */
  2571.  
  2572.     Me = FindTask(NULL);
  2573.  
  2574.     Father = (struct Task *)Me->tc_UserData;
  2575.  
  2576.         /* Snap our fingers... */
  2577.  
  2578.     if(BufferInfo = CreateBufferInfo(NULL,&SearchForward,&IgnoreCase,&WholeWords,&TopLine))
  2579.     {
  2580.             /* Open wide, here I come! */
  2581.  
  2582.         ObtainSemaphore(&BufferTaskSemaphore);
  2583.  
  2584.         BufferInfoData = BufferInfo;
  2585.  
  2586.         ReleaseSemaphore(&BufferTaskSemaphore);
  2587.  
  2588.             /* Up and running */
  2589.  
  2590.         Signal(Father,SIG_HANDSHAKE);
  2591.  
  2592.         Father = NULL;
  2593.  
  2594.             /* Swish the tinsel */
  2595.  
  2596.         RingBack = HandleBuffer(&BufferTaskSemaphore,&BufferInfoData);
  2597.  
  2598.             /* Activate the main window again */
  2599.  
  2600.         if(Window)
  2601.             BumpWindow(Window);
  2602.  
  2603.             /* The wrecking crew */
  2604.  
  2605.         DeleteBufferInfo(BufferInfo);
  2606.     }
  2607.  
  2608.         /* Shutdown in an orderly fashion */
  2609.  
  2610.     Forbid();
  2611.  
  2612.     if(RingBack)
  2613.     {
  2614.         if(Father)
  2615.             Signal(Father,SIG_HANDSHAKE);
  2616.         else
  2617.             Signal((struct Task *)ThisProcess,SIG_HANDSHAKE);
  2618.     }
  2619. }
  2620.  
  2621.     /* LaunchBuffer():
  2622.      *
  2623.      *    Launch the buffer process.
  2624.      */
  2625.  
  2626. BOOL
  2627. LaunchBuffer()
  2628. {
  2629.     ObtainSemaphore(&BufferTaskSemaphore);
  2630.  
  2631.         /* Is the buffer process already running? */
  2632.  
  2633.     if(BufferInfoData)
  2634.     {
  2635.             /* Tell it to bring its screen to the front. */
  2636.  
  2637.         Signal((struct Task *)BufferInfoData->Buddy,SIG_TOFRONT);
  2638.  
  2639.         ReleaseSemaphore(&BufferTaskSemaphore);
  2640.  
  2641.             /* Return success. */
  2642.  
  2643.         return(TRUE);
  2644.     }
  2645.     else
  2646.     {
  2647.         struct Task    *Child;
  2648.         BOOL         Result = FALSE;
  2649.  
  2650.         ReleaseSemaphore(&BufferTaskSemaphore);
  2651.  
  2652.         Forbid();
  2653.  
  2654.             /* Launch the buffer process. */
  2655.  
  2656.         if(Child = (struct Task *)CreateNewProcTags(
  2657.             NP_Entry,        BufferServer,
  2658.             NP_Name,        "term Buffer Process",
  2659.             NP_WindowPtr,    -1,
  2660.         TAG_END))
  2661.         {
  2662.             Child->tc_UserData = FindTask(NULL);
  2663.  
  2664.             WaitForHandshake();
  2665.  
  2666.             ObtainSemaphore(&BufferTaskSemaphore);
  2667.  
  2668.             if(BufferInfoData)
  2669.                 Result = TRUE;
  2670.  
  2671.             ReleaseSemaphore(&BufferTaskSemaphore);
  2672.         }
  2673.  
  2674.         Permit();
  2675.  
  2676.             /* Return the result. */
  2677.  
  2678.         return(Result);
  2679.     }
  2680. }
  2681.  
  2682.     /* TerminateBuffer():
  2683.      *
  2684.      *    Terminate the buffer process.
  2685.      */
  2686.  
  2687. VOID
  2688. TerminateBuffer()
  2689. {
  2690.     ObtainSemaphore(&BufferTaskSemaphore);
  2691.  
  2692.     if(BufferInfoData)
  2693.     {
  2694.         Forbid();
  2695.  
  2696.         ReleaseSemaphore(&BufferTaskSemaphore);
  2697.         ShakeHands((struct Task *)BufferInfoData->Buddy,SIG_KILL);
  2698.  
  2699.         Permit();
  2700.     }
  2701.     else
  2702.         ReleaseSemaphore(&BufferTaskSemaphore);
  2703. }
  2704.  
  2705.     /* MoveBuffer(TextBufferInfo *BufferInfo,BYTE Mode):
  2706.      *
  2707.      *    Move the currently displayed buffer area somewhere.
  2708.      */
  2709.  
  2710. VOID
  2711. MoveBuffer(struct SignalSemaphore *Access,struct TextBufferInfo **Data,LONG Mode)
  2712. {
  2713.     struct TextBufferInfo *BufferInfo;
  2714.  
  2715.     ObtainSemaphore(Access);
  2716.  
  2717.     BufferInfo = (TextBufferInfo *)*Data;
  2718.  
  2719.     if(BufferInfo && BufferInfo->Queue)
  2720.     {
  2721.         LONG SigBit;
  2722.  
  2723.         if((SigBit = AllocSignal(-1)) != -1)
  2724.         {
  2725.             struct DataMsg Msg;
  2726.  
  2727.             InitMsgItem(&Msg,(DESTRUCTOR)BufferDestructor);
  2728.  
  2729.             Msg.Type    = DATAMSGTYPE_MOVEREVIEW;
  2730.             Msg.Size    = Mode;
  2731.             Msg.Client    = FindTask(NULL);
  2732.             Msg.Mask    = 1L << SigBit;
  2733.  
  2734.             ClrSignal(Msg.Mask);
  2735.  
  2736.             PutMsgItem(BufferInfo->Queue,(struct MsgItem *)&Msg);
  2737.  
  2738.             ReleaseSemaphore(Access);
  2739.  
  2740.             Wait(Msg.Mask);
  2741.  
  2742.             FreeSignal(SigBit);
  2743.  
  2744.             return;
  2745.         }
  2746.     }
  2747.  
  2748.     ReleaseSemaphore(Access);
  2749. }
  2750.  
  2751.     /* NotifyBuffer(struct SignalSemaphore *Access,struct TextBufferInfo **Data,ULONG Signals):
  2752.      *
  2753.      *    Send a signal to the buffer process.
  2754.      */
  2755.  
  2756. VOID
  2757. NotifyBuffer(struct SignalSemaphore *Access,struct TextBufferInfo **Data,ULONG Signals)
  2758. {
  2759.     struct TextBufferInfo *BufferInfo;
  2760.  
  2761.     ObtainSemaphore(Access);
  2762.  
  2763.     BufferInfo = (TextBufferInfo *)*Data;
  2764.  
  2765.     if(BufferInfo && BufferInfo->Buddy)
  2766.     {
  2767.         Forbid();
  2768.  
  2769.         ReleaseSemaphore(Access);
  2770.         ShakeHands((struct Task *)BufferInfo->Buddy,Signals);
  2771.  
  2772.         Permit();
  2773.     }
  2774.     else
  2775.         ReleaseSemaphore(Access);
  2776. }
  2777.  
  2778.  
  2779. /*****************************************************************************/
  2780.  
  2781.  
  2782. STATIC VOID SAVE_DS
  2783. ReviewServer()
  2784. {
  2785.     STATIC BOOL        SearchForward    = TRUE,
  2786.                     IgnoreCase        = TRUE,
  2787.                     WholeWords        = FALSE;
  2788.     STATIC LONG        TopLine            = -1;
  2789.  
  2790.     TextBufferInfo    *BufferInfo;
  2791.     struct Task        *Father,*Me;
  2792.     BOOL             RingBack = TRUE;
  2793.  
  2794.         /* Wake this guy up */
  2795.  
  2796.     Me = FindTask(NULL);
  2797.  
  2798.     Father = (struct Task *)Me->tc_UserData;
  2799.  
  2800.         /* Snap our fingers... */
  2801.  
  2802.     if(BufferInfo = CreateBufferInfo(Window->WScreen,&SearchForward,&IgnoreCase,&WholeWords,&TopLine))
  2803.     {
  2804.             /* Open wide, here I come! */
  2805.  
  2806.         ObtainSemaphore(&ReviewTaskSemaphore);
  2807.  
  2808.         ReviewInfoData = BufferInfo;
  2809.  
  2810.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2811.  
  2812.             /* Up and running */
  2813.  
  2814.         Signal(Father,SIG_HANDSHAKE);
  2815.  
  2816.         Father = NULL;
  2817.  
  2818.             /* Swish the tinsel */
  2819.  
  2820.         RingBack = HandleBuffer(&ReviewTaskSemaphore,&ReviewInfoData);
  2821.  
  2822.         if(Config->CaptureConfig->RememberBufferWindow)
  2823.             PutWindowInfo(WINDOW_REVIEW,BufferInfo->Window->LeftEdge,BufferInfo->Window->TopEdge,BufferInfo->Window->Width,BufferInfo->Window->Height);
  2824.  
  2825.             /* Activate the main window again */
  2826.  
  2827.         if(Window)
  2828.             BumpWindow(Window);
  2829.  
  2830.             /* The wrecking crew */
  2831.  
  2832.         DeleteBufferInfo(BufferInfo);
  2833.  
  2834.         CheckItem(MEN_REVIEW_WINDOW,FALSE);
  2835.     }
  2836.  
  2837.         /* Shutdown in an orderly fashion */
  2838.  
  2839.     Forbid();
  2840.  
  2841.     if(RingBack)
  2842.     {
  2843.         if(Father)
  2844.             Signal(Father,SIG_HANDSHAKE);
  2845.         else
  2846.             Signal((struct Task *)ThisProcess,SIG_HANDSHAKE);
  2847.     }
  2848. }
  2849.  
  2850. VOID
  2851. MoveReview(LONG Mode)
  2852. {
  2853.     MoveBuffer(&ReviewTaskSemaphore,&ReviewInfoData,Mode);
  2854. }
  2855.  
  2856. VOID
  2857. DeleteReview()
  2858. {
  2859.     CheckItem(MEN_REVIEW_WINDOW,FALSE);
  2860.  
  2861.     ObtainSemaphore(&ReviewTaskSemaphore);
  2862.  
  2863.     if(ReviewInfoData)
  2864.     {
  2865.         Forbid();
  2866.  
  2867.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2868.         ShakeHands((struct Task *)ReviewInfoData->Buddy,SIG_KILL);
  2869.  
  2870.         Permit();
  2871.     }
  2872.     else
  2873.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2874. }
  2875.  
  2876. BOOL
  2877. CreateReview()
  2878. {
  2879.     BOOL Result = FALSE;
  2880.  
  2881.     ObtainSemaphore(&ReviewTaskSemaphore);
  2882.  
  2883.         /* Is the Review process already running? */
  2884.  
  2885.     if(ReviewInfoData)
  2886.     {
  2887.             /* Tell it to bring its screen to the front. */
  2888.  
  2889.         Signal((struct Task *)ReviewInfoData->Buddy,SIG_TOFRONT);
  2890.  
  2891.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2892.  
  2893.             /* Return success. */
  2894.  
  2895.         Result = TRUE;
  2896.     }
  2897.     else
  2898.     {
  2899.         struct Task    *Child;
  2900.  
  2901.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2902.  
  2903.         Forbid();
  2904.  
  2905.             /* Launch the Review process. */
  2906.  
  2907.         if(Child = (struct Task *)CreateNewProcTags(
  2908.             NP_Entry,        ReviewServer,
  2909.             NP_Name,        "term Review Process",
  2910.             NP_WindowPtr,    -1,
  2911.         TAG_END))
  2912.         {
  2913.             Child->tc_UserData = FindTask(NULL);
  2914.  
  2915.             WaitForHandshake();
  2916.  
  2917.             ObtainSemaphore(&ReviewTaskSemaphore);
  2918.  
  2919.             if(ReviewInfoData)
  2920.                 Result = TRUE;
  2921.  
  2922.             ReleaseSemaphore(&ReviewTaskSemaphore);
  2923.         }
  2924.  
  2925.         Permit();
  2926.     }
  2927.  
  2928.     if(Result)
  2929.         CheckItem(MEN_REVIEW_WINDOW,TRUE);
  2930.  
  2931.     return(Result);
  2932. }
  2933.